/** \file
 *  \brief  Application examples that Use the ATSHA204 Library
 *  \author Atmel Crypto Products
 *  \date   January 15, 2013

 * \copyright Copyright (c) 2013 Atmel Corporation. All rights reserved.
 *
 * \atsha204_library_license_start
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel integrated circuit.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \atsha204_library_license_stop
 *
*/

/** \defgroup atsha204_examples Module 12: Example Functions
<ul>
	<li>sha204e_checkmac_device:<br>
		Demonstrates communication using a MAC - CheckMac command sequence with
		relatively low security (mode 0: no Nonce), but little code space usage.
	</li>
	<li>
		sha204e_checkmac_firmware:<br>
		Demonstrates high security using a Nonce - GenDig - MAC command sequence
		and MAC verification in firmware. This requires more code space because
		a sha256 implementation in firmware is needed. Also, the firmware has to
		be able to access keys. Having a key stored outside the device poses a
		higher security risk.
	</li>
	<li>
		sha204e_checkmac_derive_key:<br>
		Demonstrates high security in a host / client scenario using a DeriveKey /
		MAC command sequence on one device (client) and a GenDig / CheckMac sequence
		on another device (host). No sha256 implementation in firmware is needed.
		All keys are only stored on the devices and never revealed. When using
		I<SUP>2</SUP>C you have to change the address of one of the devices first.
		Connect only one device to your CPU and use \ref sha204e_change_i2c_address
		to change it.<br>
		This example needs modifications introducing the Pause command when using
		the SWI UART interface.
	</li>
	<li>
		sha204e_checkmac_diversify_key:<br>
		Demonstrates high security in a host / client scenario using a
		Read / MAC command sequence on one device (client) and a GenDig / CheckMac
		sequence on another device (host). The MAC command uses a key id for a key
		that was diversified from the serial number of the client.
		No sha256 implementation in firmware is needed.
		All keys are only stored on the devices and never revealed. When using
		I<SUP>2</SUP>C you have to change the address of one of the devices first.
		Connect only one device to your CPU and use \ref sha204e_change_i2c_address
		to change it.<br>
		This example needs modifications introducing the Pause command when using
		the SWI UART interface.
	</li>
	<li>
		sha204e_change_i2c_address:<br>
		This is a utility function that changes the I<SUP>2</SUP>C address of a device so that
		you can run the \ref sha204e_checkmac_derived_key example when using I<SUP>2</SUP>C.
		Make sure that you don't have more than one device with the same address
		sitting on the bus.
	</li>
	<li>
		sha204e_read_config_zone:<br>
		This function reads all 88 bytes from the configuration zone. Since it does
		not depend on how the device is personalized or the lock status of the device,
		it is a good starting point to work with the library.
	</li>
</ul>

The example functions for SHA204_EXAMPLE_CHECKMAC_DEVICE and
SHA204_EXAMPLE_CHECKMAC_FIRMWARE use the sha204m_execute function that can be used
to send any ATSHA204 command. The other example functions use sha204m_... command wrapper
functions. Using only the sha204m_execute function in your application might compile into
smaller code size compared to using the command wrapper functions. You can use any
approach, but if you use the wrapper functions make sure you allow the compiler and linker
to garbage collect functions or remove unused functions manually to keep code size to a
minimum.

Examples that use an ATSHA204 as host you can run conveniently on an AT88CK109STK3
("Microbase" with 3-pin "Javan" kit, SWI). When using I<SUP>2</SUP>C, you can use the
AT88CK109STK8 version ("Microbase" with 8-pin "Javan" kit), but you have to change
the default I<SUP>2</SUP> address of one of the two devices first.

CAUTION WHEN DEBUGGING: Be aware of the timeout feature of the device. The
device will go to sleep between 0.7 and 1.7 seconds after a Wakeup. This timeout
cannot be re-started by any means. It only starts after a Wakeup pulse while the
device is in Idle or Sleep mode. When hitting a break point, this timeout will kick in
and the device has gone to sleep before you continue debugging. Therefore, after you have
examined variables you have to restart your debug session if the device was awake at
that point.
@{ */

#include "Global.h"//#include <string.h>                   // needed for memset(), memcpy()
//#include "sha204_lib_return_codes.h"  // declarations of function return codes
//#include "sha204_comm_marshaling.h"   // definitions and declarations for the Command Marshaling module
//#include "sha204_helper.h"            // definitions of functions that calculate SHA256 for every command
//#include "sha204_examples.h"          // definitions and declarations for example functions
#include "UserCommonInclude.h"
#if(_ENCRYPTION_OPTION)

#define _SHA204_ADDRESS					0xC8
#define _IIC_SW_BUS						_IIC_SYS_EEPROM//_IIC_AB_BUS//_IIC_SYS_EEPROM//_IIC_AB_BUS
#define _IIC_HW_PIN						_SW_IIC_PIN_GPIO//_HW_IIC_PIN_198_199//_SW_IIC_PIN_GPIO

#define SHA204_KEY_ID           ( 0)

#define SHA204_CMD_SIZE_MIN          ((uint8_t)  7)

#define SHA204_RSP_SIZE_MIN          ((uint8_t)  4)  //!< minimum number of bytes in response
#define SHA204_RSP_SIZE_MAX          ((uint8_t) 35)  //!< maximum size of response packet

#define SHA204_CHECKMAC                 ((uint8_t) 0x28)       //!< CheckMac command op-code
#define SHA204_DERIVE_KEY               ((uint8_t) 0x1C)       //!< DeriveKey command op-code
#define SHA204_DEVREV                   ((uint8_t) 0x30)       //!< DevRev command op-code
#define SHA204_GENDIG                   ((uint8_t) 0x15)       //!< GenDig command op-code
#define SHA204_HMAC                     ((uint8_t) 0x11)       //!< HMAC command op-code
#define SHA204_LOCK                     ((uint8_t) 0x17)       //!< Lock command op-code
#define SHA204_MAC                      ((uint8_t) 0x08)       //!< MAC command op-code
#define SHA204_NONCE                    ((uint8_t) 0x16)       //!< Nonce command op-code
#define SHA204_PAUSE                    ((uint8_t) 0x01)       //!< Pause command op-code
#define SHA204_RANDOM                   ((uint8_t) 0x1B)       //!< Random command op-code
#define SHA204_READ                     ((uint8_t) 0x02)       //!< Read command op-code
#define SHA204_UPDATE_EXTRA             ((uint8_t) 0x20)       //!< UpdateExtra command op-code
#define SHA204_WRITE                    ((uint8_t) 0x12)       //!< Write command op-code


#define SHA204_SUCCESS              ((uint8_t)  0x00) //!< Function succeeded.
#define SHA204_CHECKMAC_FAILED		((uint8_t)  0xD1) //!< response status byte indicates CheckMac failure
#define SHA204_PARSE_ERROR          ((uint8_t)  0xD2) //!< response status byte indicates parsing error
#define SHA204_CMD_FAIL             ((uint8_t)  0xD3) //!< response status byte indicates command execution error
#define SHA204_STATUS_CRC           ((uint8_t)  0xD4) //!< response status byte indicates CRC error
#define SHA204_STATUS_UNKNOWN       ((uint8_t)  0xD5) //!< response status byte is unknown
#define SHA204_FUNC_FAIL            ((uint8_t)  0xE0) //!< Function could not execute due to incorrect condition / state.
#define SHA204_GEN_FAIL             ((uint8_t)  0xE1) //!< unspecified error
#define SHA204_BAD_PARAM            ((uint8_t)  0xE2) //!< bad argument (out of range, null pointer, etc.)
#define SHA204_INVALID_ID           ((uint8_t)  0xE3) //!< invalid device id, id not set
#define SHA204_INVALID_SIZE         ((uint8_t)  0xE4) //!< Count value is out of range or greater than buffer size.
#define SHA204_BAD_CRC              ((uint8_t)  0xE5) //!< incorrect CRC received
#define SHA204_RX_FAIL              ((uint8_t)  0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0.
#define SHA204_RX_NO_RESPONSE       ((uint8_t)  0xE7) //!< Not an error while the Command layer is polling for a command response.
#define SHA204_RESYNC_WITH_WAKEUP   ((uint8_t)  0xE8) //!< Re-synchronization succeeded, but only after generating a Wake-up

#define SHA204_COMM_FAIL            ((uint8_t)  0xF0) //!< Communication with device failed. Same as in hardware dependent modules.
#define SHA204_TIMEOUT              ((uint8_t)  0xF1) //!< Timed out while waiting for response. Number of bytes received is 0.

#define SHA204_COUNT_IDX                ( 0)                   //!< command packet index for count
#define SHA204_OPCODE_IDX               ( 1)                   //!< command packet index for op-code
#define SHA204_PARAM1_IDX               ( 2)                   //!< command packet index for first parameter
#define SHA204_PARAM2_IDX               ( 3)                   //!< command packet index for second parameter
#define SHA204_DATA_IDX                 ( 5)                   //!< command packet index for data load

#define NONCE_MODE_IDX                  SHA204_PARAM1_IDX      //!< Nonce command index for mode
#define NONCE_PARAM2_IDX                SHA204_PARAM2_IDX      //!< Nonce command index for 2. parameter
#define NONCE_INPUT_IDX                 SHA204_DATA_IDX        //!< Nonce command index for input data
#define NONCE_COUNT_SHORT               (27)                   //!< Nonce command packet size for 20 bytes of data
#define NONCE_COUNT_LONG                (39)                   //!< Nonce command packet size for 32 bytes of data
#define NONCE_MODE_MASK                 ((uint8_t) 3)          //!< Nonce mode bits 2 to 7 are 0.
#define NONCE_MODE_SEED_UPDATE          ((uint8_t) 0x00)       //!< Nonce mode: update seed
#define NONCE_MODE_NO_SEED_UPDATE       ((uint8_t) 0x01)       //!< Nonce mode: do not update seed
#define NONCE_MODE_INVALID              ((uint8_t) 0x02)       //!< Nonce mode 2 is invalid.
#define NONCE_MODE_PASSTHROUGH          ((uint8_t) 0x03)       //!< Nonce mode: pass-through
#define NONCE_NUMIN_SIZE                (20)                   //!< Nonce data length
#define NONCE_NUMIN_SIZE_PASSTHROUGH    (32)                   //!< Nonce data length in pass-through mode (mode = 3)

#define CPU_CLOCK_DEVIATION_NEGATIVE   (0.99)
#define CPU_CLOCK_DEVIATION_POSITIVE   (1.01)

#define NONCE_DELAY                     ((uint8_t) (/*22.0 */32 * CPU_CLOCK_DEVIATION_NEGATIVE + 0.5))
#define NONCE_EXEC_MAX                   ((uint8_t) (60.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))

#define MAC_DELAY                       ((uint8_t) (/*12.0*/18 * CPU_CLOCK_DEVIATION_NEGATIVE + 0.5))
#define MAC_EXEC_MAX                     ((uint8_t) (/*35.0*/50 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))

#define SHA204_RSP_SIZE_VAL             ((uint8_t)  7)         //!< size of response packet containing four bytes of data
#define SHA204_KEY_SIZE                 (32)                   //!< size of key
#define SHA204_KEY_COUNT                (16)                   //!< number of keys
#define SHA204_CONFIG_SIZE              (88)                   //!< size of configuration zone
#define SHA204_OTP_SIZE                 (64)                   //!< size of OTP zone
#define SHA204_DATA_SIZE                (SHA204_KEY_COUNT * SHA204_KEY_SIZE) //!< size of data zone

#define CHECKMAC_RSP_SIZE               SHA204_RSP_SIZE_MIN    //!< response size of DeriveKey command
#define DERIVE_KEY_RSP_SIZE             SHA204_RSP_SIZE_MIN    //!< response size of DeriveKey command
#define DEVREV_RSP_SIZE                 SHA204_RSP_SIZE_VAL    //!< response size of DevRev command returns 4 bytes
#define GENDIG_RSP_SIZE                 SHA204_RSP_SIZE_MIN    //!< response size of GenDig command
#define HMAC_RSP_SIZE                   SHA204_RSP_SIZE_MAX    //!< response size of HMAC command
#define LOCK_RSP_SIZE                   SHA204_RSP_SIZE_MIN    //!< response size of Lock command
#define MAC_RSP_SIZE                    SHA204_RSP_SIZE_MAX    //!< response size of MAC command
#define NONCE_RSP_SIZE_SHORT            SHA204_RSP_SIZE_MIN    //!< response size of Nonce command with mode[0:1] = 3
#define NONCE_RSP_SIZE_LONG             SHA204_RSP_SIZE_MAX    //!< response size of Nonce command
#define PAUSE_RSP_SIZE                  SHA204_RSP_SIZE_MIN    //!< response size of Pause command
#define RANDOM_RSP_SIZE                 SHA204_RSP_SIZE_MAX    //!< response size of Random command
#define READ_4_RSP_SIZE                 SHA204_RSP_SIZE_VAL    //!< response size of Read command when reading 4 bytes
#define READ_32_RSP_SIZE                SHA204_RSP_SIZE_MAX    //!< response size of Read command when reading 32 bytes
#define UPDATE_RSP_SIZE                 SHA204_RSP_SIZE_MIN    //!< response size of UpdateExtra command
#define WRITE_RSP_SIZE                  SHA204_RSP_SIZE_MIN    //!< response size of Write command

#define SHA204_COMMAND_EXEC_MAX      ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
#define SHA204_CRC_SIZE              ((uint8_t)  2)

#define SHA204_BUFFER_POS_COUNT      (0)             //!< buffer index of count byte in command or response
#define SHA204_BUFFER_POS_DATA       (1)             //!< buffer index of data in response

#define SHA204_RETRY_COUNT           (1)

// error codes for physical hardware dependent module
// Codes in the range 0x00 to 0xF7 are shared between physical interfaces (SWI, TWI, SPI).
// Codes in the range 0xF8 to 0xFF are special for the particular interface.
#define I2C_FUNCTION_RETCODE_SUCCESS     ((uint8_t) 0x00) //!< Communication with device succeeded.
#define I2C_FUNCTION_RETCODE_COMM_FAIL   ((uint8_t) 0xF0) //!< Communication with device failed.
#define I2C_FUNCTION_RETCODE_TIMEOUT     ((uint8_t) 0xF1) //!< Communication timed out.
#define I2C_FUNCTION_RETCODE_NACK        ((uint8_t) 0xF8) //!< TWI nack

#define SWI_RECEIVE_TIME_OUT      ((uint16_t) 153)
#define SWI_US_PER_BYTE           ((uint16_t) 313)
#define CHECKMAC_COUNT                  (84)                   //!< CheckMAC command packet size

#define SHA204_RESPONSE_TIMEOUT   ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE)
#define SHA204_BUFFER_POS_STATUS     (1)
#define SHA204_STATUS_BYTE_PARSE     ((uint8_t) 0x03)
#define SHA204_STATUS_BYTE_EXEC      ((uint8_t) 0x0F)
#define SHA204_STATUS_BYTE_COMM      ((uint8_t) 0xFF)

#define SHA204_MSG_SIZE_NONCE            (55)

#define SHA204_PACKET_OVERHEAD           ( 3)
#define SHA256_BLOCK_SIZE   (64)   // bytes

#define GENDIG_ZONE_DATA                ((uint8_t) 2)          //!< GenDig zone id data
#define GENDIG_ZONE_OTP                 ((uint8_t) 1)          //!< GenDig zone id OTP
#define GENDIG_DELAY                    ((uint8_t) (/*11.0*/16 * CPU_CLOCK_DEVIATION_NEGATIVE + 0.5))
#define GENDIG_EXEC_MAX                  ((uint8_t) (/*43.0 */50* CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
#define GENDIG_ZONE_CONFIG              ((uint8_t) 0)          //!< GenDig zone id config

#define READ_COUNT                      SHA204_CMD_SIZE_MIN    //!< Read command packet size
#define SHA204_ZONE_CONFIG              ((uint8_t)  0x00)      //!< Configuration zone
#define SHA204_ZONE_ACCESS_32           ((uint8_t)    32)      //!< Read or write 32 bytes.
#define READ_ZONE_MODE_32_BYTES         ((uint8_t) 0x80)       //!< Read mode: 32 bytes
#define SHA204_ZONE_ACCESS_4            ((uint8_t)     4)      //!< Read or write 4 bytes.
#define READ_ZONE_MASK                  ((uint8_t) 0x83)       //!< Read zone bits 2 to 6 are 0.
#define SHA204_ZONE_OTP                 ((uint8_t)  0x01)      //!< OTP (One Time Programming) zone
#define SHA204_ZONE_MASK                ((uint8_t)  0x03)      //!< Zone mask
#define SHA204_ADDRESS_MASK_CONFIG      (         0x001F)      //!< Address bits 5 to 7 are 0 for Configuration zone.
#define SHA204_ADDRESS_MASK_OTP         (         0x000F)      //!< Address bits 4 to 7 are 0 for OTP zone.
#define SHA204_ADDRESS_MASK             (         0x007F)      //!< Address bit 7 to 15 are always 0.
#define SHA204_ZONE_DATA                ((uint8_t)  0x02)      //!< Data zone

#define READ_ZONE_IDX                   SHA204_PARAM1_IDX      //!< Read command index for zone
#define READ_ADDR_IDX                   SHA204_PARAM2_IDX      //!< Read command index for address
#define SHA204_ZONE_COUNT_FLAG          ((uint8_t)  0x80)      //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes.
#define READ_DELAY                      ((uint8_t) ( 1))
#define READ_EXEC_MAX                    ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
#define SHA204_MSG_SIZE_GEN_DIG          (96)
#define SHA204_SN_0                    (0x01)
#define SHA204_SN_1                    (0x23)
#define SHA204_SN_8                    (0xEE)
#define SHA204_GENDIG_ZEROS_SIZE         (25)

#define MAC_MODE_BLOCK1_TEMPKEY         ((uint8_t) 0x02)       //!< MAC mode bit   1: first SHA block from TempKey
#define MAC_MODE_BLOCK2_TEMPKEY         ((uint8_t) 0x01)       //!< MAC mode bit   0: second SHA block from TempKey

#define MAC_MODE_MASK                   ((uint8_t) 0x77)       //!< MAC mode bits 3 and 7 are 0.
#define CHECKMAC_CLIENT_RESPONSE_SIZE   (32)                   //!< CheckMAC size of client response

#define SHA204_MSG_SIZE_MAC              (88)
#define MAC_MODE_USE_TEMPKEY_MASK      ((uint8_t) 0x03)
#define MAC_MODE_INCLUDE_OTP_64         ((uint8_t) 0x20)       //!< MAC mode bit   5: include first 64 OTP bits
#define MAC_MODE_INCLUDE_SN             ((uint8_t) 0x40)       //!< MAC mode bit   6: include serial number
#define MAC_MODE_INCLUDE_OTP_88         ((uint8_t) 0x10)       //!< MAC mode bit   4: include first 88 OTP bits
#define MAC_MODE_SOURCE_FLAG_MATCH      ((uint8_t) 0x04)       //!< MAC mode bit   2: match TempKey.SourceFlag

#define SHA204_OTP_SIZE_8                ( 8)
#define SHA204_OTP_SIZE_3                ( 3)
#define SHA204_SN_SIZE_4                 ( 4)
#define SHA204_SN_SIZE_2                 ( 2)

BYTE data pIICArray[16];

#define rotate_right(value, places) ((value >> places) | (value << (32 - places)))

extern BYTE ScalerMcuIICStart(BYTE ucSlaveAddr);
extern void ScalerMcuIICStop(void);
extern BYTE i2c_send_bytes(BYTE count, BYTE *data_r);
extern uint8_t i2c_receive_bytes(WORD usLength,uint8_t *pReadArray);

enum i2c_word_address {
	SHA204_I2C_PACKET_FUNCTION_RESET,  //!< Reset device.
	SHA204_I2C_PACKET_FUNCTION_SLEEP,  //!< Put device into Sleep mode.
	SHA204_I2C_PACKET_FUNCTION_IDLE,   //!< Put device into Idle mode.
	SHA204_I2C_PACKET_FUNCTION_NORMAL  //!< Write / evaluate data that follow this word address byte.
};
struct sha204h_nonce_in_out {
	uint8_t mode; 
	uint8_t *num_in;
	uint8_t *rand_out;
	struct sha204h_temp_key *temp_key;
};
struct sha204h_temp_key {
	uint8_t value[SHA204_KEY_SIZE];
	unsigned int key_id      : 4;     
	unsigned int source_flag : 1;
	unsigned int gen_data    : 1;
	unsigned int check_flag  : 1;
	unsigned int valid       : 1;
};
struct sha204h_gen_dig_in_out {
	uint8_t zone;
	uint16_t key_id;
	uint8_t *stored_value;
	struct sha204h_temp_key *temp_key;
};
struct sha204h_mac_in_out {
	uint8_t mode;
	uint16_t key_id;
	uint8_t *challenge;
	uint8_t *key;
	uint8_t *otp;
	uint8_t *sn;
	uint8_t *response;
	struct sha204h_temp_key *temp_key;
};
struct sha204h_include_data_in_out {
	uint8_t *p_temp;
	uint8_t *otp;
	uint8_t *sn;
	uint8_t mode;
};

void sha204c_calculate_crc(uint8_t length, uint8_t *crc_source, uint8_t *crc) {
	uint8_t counter;
	uint16_t crc_register = 0;
	uint16_t polynom = 0x8005;
	uint8_t shift_register;
	uint8_t data_bit, crc_bit;

	for (counter = 0; counter < length; counter++) {
	  for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
		 data_bit = (crc_source[counter] & shift_register) ? 1 : 0;
		 crc_bit = (crc_register >> 15);
		 crc_register <<= 1;
		 if (data_bit != crc_bit)
			crc_register ^= polynom;
	  }
	}
	crc[0] = (uint8_t) (crc_register & 0x00FF);
	crc[1] = (uint8_t) (crc_register >> 8);
}

#if 0
/** \brief key values at time of shipping
*/
const uint8_t sha204_default_key[16][SHA204_KEY_SIZE] = {
	{
		0x00, 0x00, 0x00, 0x0A, 0xA1, 0x1A, 0xAC, 0xC5, 0x57, 0x7F, 0xFF, 0xF4, 0x40, 0x04, 0x4E, 0xE4,
		0x45, 0x5D, 0xD4, 0x40, 0x04, 0x40, 0x01, 0x1B, 0xBD, 0xD0, 0x0E, 0xED, 0xD3, 0x3C, 0xC6, 0x67,
	},
	{
		0x11, 0x11, 0x11, 0x12, 0x23, 0x3B, 0xB6, 0x6C, 0xCC, 0xC5, 0x53, 0x3B, 0xB7, 0x7B, 0xB9, 0x9E,
		0xE9, 0x9B, 0xBB, 0xB5, 0x51, 0x1F, 0xFD, 0xD2, 0x2F, 0xF7, 0x74, 0x4C, 0xCD, 0xD0, 0x0E, 0xE9,
	},
	{
		0x22, 0x22, 0x22, 0x2C, 0xC1, 0x17, 0x7C, 0xC1, 0x1C, 0xC4, 0x4D, 0xD5, 0x56, 0x68, 0x89, 0x9A,
		0xAA, 0xA0, 0x00, 0x04, 0x43, 0x3E, 0xE3, 0x39, 0x9C, 0xCF, 0xFB, 0xB6, 0x6B, 0xB0, 0x0B, 0xB6,
	},
	{
		0x33, 0x33, 0x33, 0x33, 0x33, 0x36, 0x61, 0x14, 0x4A, 0xA1, 0x17, 0x79, 0x9A, 0xA2, 0x23, 0x36,
		0x6C, 0xC7, 0x7F, 0xFE, 0xE4, 0x4B, 0xBE, 0xE2, 0x2F, 0xF1, 0x13, 0x32, 0x20, 0x06, 0x67, 0x79,
	},
	{
		0x44, 0x44, 0x44, 0x49, 0x91, 0x11, 0x18, 0x86, 0x68, 0x83, 0x3D, 0xDB, 0xB8, 0x8D, 0xD3, 0x3F,
		0xF8, 0x85, 0x57, 0x70, 0x0C, 0xC7, 0x74, 0x42, 0x2E, 0xED, 0xDA, 0xAD, 0xDA, 0xA5, 0x52, 0x28,
	},
	{
		0x55, 0x55, 0x55, 0x58, 0x86, 0x6F, 0xF2, 0x2B, 0xB3, 0x32, 0x20, 0x09, 0x98, 0x8A, 0xA6, 0x6E,
		0xE1, 0x1E, 0xE6, 0x63, 0x33, 0x37, 0x7A, 0xA5, 0x52, 0x20, 0x01, 0x10, 0x03, 0x36, 0x6A, 0xA0,
	},
	{
		0x66, 0x66, 0x66, 0x6D, 0xD0, 0x04, 0x45, 0x53, 0x3A, 0xAC, 0xC2, 0x22, 0x25, 0x55, 0x57, 0x7F,
		0xF6, 0x6D, 0xD4, 0x46, 0x6B, 0xB7, 0x7D, 0xDD, 0xDF, 0xF9, 0x96, 0x68, 0x89, 0x9D, 0xDA, 0xA2,
	},
	{
		0x77, 0x77, 0x77, 0x72, 0x2F, 0xF4, 0x4A, 0xA9, 0x9C, 0xCC, 0xC0, 0x05, 0x5E, 0xE4, 0x45, 0x59,
		0x99, 0x9B, 0xBD, 0xD2, 0x26, 0x69, 0x96, 0x6D, 0xDD, 0xD4, 0x49, 0x9F, 0xF8, 0x8A, 0xA5, 0x50,
	},
	{
		0x88, 0x88, 0x88, 0x8C, 0xC6, 0x62, 0x2A, 0xAF, 0xFE, 0xE1, 0x1F, 0xF8, 0x82, 0x2D, 0xD4, 0x4E,
		0xE0, 0x08, 0x85, 0x58, 0x85, 0x53, 0x34, 0x44, 0x4D, 0xD7, 0x77, 0x7B, 0xB8, 0x89, 0x9D, 0xDE,
	},
	{
		0x99, 0x99, 0x99, 0x94, 0x4E, 0xE6, 0x6D, 0xD4, 0x4A, 0xAF, 0xF5, 0x59, 0x92, 0x23, 0x30, 0x06,
		0x6B, 0xBD, 0xD2, 0x2D, 0xD5, 0x52, 0x27, 0x77, 0x7D, 0xD7, 0x77, 0x7B, 0xB3, 0x39, 0x95, 0x5E,
	},
	{
		0xAA, 0xAA, 0xAA, 0xA1, 0x15, 0x5A, 0xA2, 0x25, 0x55, 0x50, 0x0B, 0xBD, 0xD2, 0x2E, 0xEA, 0xA9,
		0x9A, 0xAF, 0xF2, 0x29, 0x96, 0x64, 0x46, 0x61, 0x15, 0x56, 0x69, 0x91, 0x11, 0x11, 0x12, 0x29,
	},
	{
		0xBB, 0xBB, 0xBB, 0xB2, 0x24, 0x4D, 0xDB, 0xB7, 0x78, 0x8A, 0xA8, 0x87, 0x70, 0x06, 0x64, 0x4A,
		0xA1, 0x1F, 0xF0, 0x08, 0x8D, 0xDC, 0xC9, 0x91, 0x17, 0x79, 0x96, 0x66, 0x60, 0x00, 0x0A, 0xAF,
	},
	{
		0xCC, 0xCC, 0xCC, 0xCC, 0xC6, 0x61, 0x17, 0x71, 0x1A, 0xA5, 0x52, 0x24, 0x45, 0x5A, 0xAC, 0xCD,
		0xD2, 0x29, 0x92, 0x24, 0x46, 0x62, 0x28, 0x89, 0x90, 0x06, 0x62, 0x24, 0x4C, 0xCA, 0xA5, 0x56,
	},
	{
		0xDD, 0xDD, 0xDD, 0xDB, 0xBF, 0xFA, 0xAC, 0xC1, 0x11, 0x17, 0x70, 0x05, 0x55, 0x59, 0x9C, 0xCC,
		0xC9, 0x9B, 0xB6, 0x62, 0x28, 0x80, 0x0F, 0xF9, 0x92, 0x29, 0x95, 0x5D, 0xDF, 0xF3, 0x30, 0x00,
	},
	{
		0xEE, 0xEE, 0xEE, 0xE0, 0x08, 0x85, 0x55, 0x57, 0x77, 0x7B, 0xBD, 0xDA, 0xA7, 0x7B, 0xB8, 0x8A,
		0xA7, 0x7A, 0xAF, 0xF5, 0x58, 0x8D, 0xD1, 0x18, 0x8B, 0xB9, 0x92, 0x2F, 0xF0, 0x0D, 0xDF, 0xF7,
	},
	{
		0xFF, 0xFF, 0xFF, 0xF6, 0x68, 0x8B, 0xB7, 0x7B, 0xB8, 0x80, 0x01, 0x1B, 0xBE, 0xE6, 0x66, 0x62,
		0x2C, 0xCE, 0xEC, 0xC7, 0x74, 0x46, 0x68, 0x80, 0x0F, 0xFE, 0xE4, 0x47, 0x7D, 0xDC, 0xC1, 0x1C,
	},
};


/** 
 * \brief This function wraps \ref sha204p_sleep().
 *
 *        It puts both devices to sleep if two devices (client and host) are used.
 *        This function is also called when a Wakeup did not succeed. 
 *        This would not make sense if a device did not wakeup and it is the only
 *        device on SDA, but if there are two devices (client and host) that
 *        share SDA, the device that is not selected has also woken up.
 */
void sha204e_sleep() 
{
#if defined(SHA204_I2C) && (SHA204_CLIENT_ADDRESS != SHA204_HOST_ADDRESS)
	// Select host device...
	sha204p_set_device_id(SHA204_HOST_ADDRESS);
	// and put it to sleep.
	(void) sha204p_sleep();
	// Select client device...
	sha204p_set_device_id(SHA204_CLIENT_ADDRESS);
	// and put it to sleep.
	(void) sha204p_sleep();
#else	
	(void) sha204p_sleep();
#endif
}


/** \brief This function wakes up two I<SUP>2</SUP>C devices and puts one back to
           sleep, effectively waking up only one device among two that share the bus.
	\param[in] device_id which device to wake up
	\return status of the operation
*/
uint8_t sha204e_wakeup_device(uint8_t device_id)
{
	uint8_t ret_code;
	uint8_t wakeup_response[SHA204_RSP_SIZE_MIN];

	sha204p_set_device_id(device_id);

	// Wake up the devices.
	memset(wakeup_response, 0, sizeof(wakeup_response));
	ret_code = sha204c_wakeup(wakeup_response);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}

#if defined(SHA204_I2C) && (SHA204_CLIENT_ADDRESS != SHA204_HOST_ADDRESS)
	// SHA204 I2C devices can share SDA. We have to put the other device back to sleep.
	// Select other device...
	sha204p_set_device_id(device_id == SHA204_CLIENT_ADDRESS ? SHA204_HOST_ADDRESS : SHA204_CLIENT_ADDRESS);
	// and put it to sleep.
	ret_code = sha204p_sleep();
	
	// Now select the device we want to communicate with.
	sha204p_set_device_id(device_id);
#endif

	return ret_code;	
}


/** \brief This function checks the response status byte and puts the device
           to sleep if there was an error.
   \param[in] ret_code return code of function
	\param[in] response pointer to response buffer
	\return status of the operation
*/
uint8_t sha204e_check_response_status(uint8_t ret_code, uint8_t *response)
{
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
	ret_code = response[SHA204_BUFFER_POS_STATUS];
	if (ret_code != SHA204_SUCCESS)
		sha204p_sleep();

	return ret_code;	
}


/** \brief This function reads the serial number from the device.
 *
           The serial number is stored in bytes 0 to 3 and 8 to 12
           of the configuration zone.
   \param[in] tx_buffer pointer to transmit buffer.
	\param[out] sn pointer to nine-byte serial number
	\return status of the operation
*/
uint8_t sha204e_read_serial_number(uint8_t *tx_buffer, uint8_t *sn)
{
	uint8_t rx_buffer[READ_32_RSP_SIZE];
	
	uint8_t status = sha204m_read(tx_buffer, rx_buffer, 
						SHA204_ZONE_COUNT_FLAG | SHA204_ZONE_CONFIG, 0);
	if (status != SHA204_SUCCESS)
		sha204p_sleep();
	
	memcpy(sn, &rx_buffer[SHA204_BUFFER_POS_DATA], 4);
	memcpy(sn + 4, &rx_buffer[SHA204_BUFFER_POS_DATA + 8], 5);
	
	return status;
}


/** \brief This function locks the configuration zone.
    
	It first reads it and calculates the CRC of its content.
	It then sends a Lock command to the device.
	
	This function is disabled by default with the
	\ref SHA204_EXAMPLE_CONFIG_WITH_LOCK switch.

	Once the configuration zone is locked, the Random
	command returns a number from its high quality random
	number generator instead of a 0xFFFF0000FFFF0000...
	sequence.

	\param[in] device_id which device to lock
	\return status of the operation
*/
uint8_t sha204e_lock_config_zone(uint8_t device_id)
{
	uint8_t ret_code;
	uint8_t config_data[SHA204_CONFIG_SIZE];
	uint8_t crc_array[SHA204_CRC_SIZE];
	uint16_t crc;
	uint8_t command[LOCK_COUNT];
	uint8_t response[LOCK_RSP_SIZE];
	
	sha204p_sleep();
	
	ret_code = sha204e_read_config_zone(device_id, config_data);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	// Check whether the configuration zone is locked already.
	if (config_data[87] == 0)
		return ret_code;
	
	sha204c_calculate_crc(sizeof(config_data), config_data, crc_array);
	crc = (crc_array[1] << 8) + crc_array[0];

	ret_code = sha204c_wakeup(response);
	ret_code = sha204m_lock(command, response, SHA204_ZONE_CONFIG, crc);
	
	return ret_code;
}


/** \brief This function configures a child and parent key for derived key scenarios.
 *
 *         To run this scenario successfully the client device has
 *         to be configured first: We use a key slot in the client device that is already
 *         configured for this purpose, but we need to point to a parent whose
 *         CheckOnly flag is set on the host device. On the client device we have
 *         to reset this bit, otherwise the DeriveKey command would return an error.
 *         Key id 10 is chosen for the child key because only its parent key needs to be changed
 *         from its default configuration. Key id 13 is chosen for the parent key because only
 *         its CheckOnly flag has to be reset compared to its default configuration.
    \return status of the operation
*/
uint8_t sha204e_configure_key()
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;

	const uint8_t config_child = 0x7D;
	const uint8_t config_parent = 0xCD;
	const uint8_t config_address = 32;
	
	// Make the command buffer the long size (32 bytes, no MAC) of the Write command.
	uint8_t command[WRITE_COUNT_LONG];
	
	uint8_t data_load[SHA204_ZONE_ACCESS_32];

	// Make the response buffer the size of a Read response.
	uint8_t response[READ_32_RSP_SIZE];

	// Wake up the client device.
	ret_code = sha204e_wakeup_device(SHA204_CLIENT_ADDRESS);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
	
	// Read client device configuration for child key.
	memset(response, 0, sizeof(response));
	ret_code = sha204m_read(command, response, SHA204_ZONE_COUNT_FLAG | SHA204_ZONE_CONFIG, config_address);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}

	// Check whether we configured already. If so, exit here.
	if ((response[SHA204_BUFFER_POS_DATA + 9] == config_child)
		&& (response[SHA204_BUFFER_POS_DATA + 14] == config_parent)) {
		sha204p_sleep();
		return ret_code;
	}

	// Write client configuration.
	memcpy(data_load, &response[SHA204_BUFFER_POS_DATA], sizeof(data_load));
	data_load[9] = config_child;
	data_load[14] = config_parent;
	ret_code = sha204m_write(command, response, SHA204_ZONE_COUNT_FLAG | SHA204_ZONE_CONFIG,
							config_address, data_load, NULL);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}

	sha204p_sleep();
	
	return ret_code;
}


/** \brief This function configures the client for the derived key and
 *         diversified key example.
 *
 *         Creating a derived key allows a host device to check a MAC
 *         in a highly secure fashion. No replay attacks are possible
 *         and SHA256 calculation in firmware is not needed.
 * \return status of the operation
 */
uint8_t sha204e_configure_derive_key()
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;

	// Configure key.
	ret_code = sha204e_configure_key();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
	
#if (SHA204_EXAMPLE_CONFIG_WITH_LOCK != 0)
	ret_code = sha204e_lock_config_zone(SHA204_HOST_ADDRESS);
#endif

	return ret_code;
}


/** \brief This function configures a client device for the diversified key example.
 *
 *         After configuration is done, the diversified key is programmed with the following
 *         command sequence:
 *         - Read 9-byte serial number from configuration zone and pad it with 23 zeros.
 *         - Send the zero padded serial number with a Nonce command (mode = pass-through).
 *         - Send a DeriveKey command with the child identifier as the target.
 * \return status of the operation
 */
uint8_t sha204e_configure_diversify_key(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;
	
	uint8_t command[NONCE_COUNT_LONG];
	uint8_t response[SHA204_RSP_SIZE_MIN];
	uint8_t data_load[NONCE_NUMIN_SIZE_PASSTHROUGH];

	// Configure key.
	ret_code = sha204e_configure_key();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	// Wake up the client device.
	ret_code = sha204e_wakeup_device(SHA204_CLIENT_ADDRESS);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	// Read serial number and pad it.
	memset(data_load, 0, sizeof(data_load));
	ret_code = sha204e_read_serial_number(command, data_load);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
	
	//  Put padded serial number into TempKey (fixed Nonce).
	ret_code = sha204m_nonce(command, response, NONCE_MODE_PASSTHROUGH, data_load);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
	
	//  Send DeriveKey command.
	ret_code = sha204m_derive_key(command, response, DERIVE_KEY_RANDOM_FLAG, SHA204_KEY_CHILD, NULL);
	
#ifdef SHA204_EXAMPLE_CONFIG_WITH_LOCK
	sha204p_sleep();

	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	ret_code = sha204e_lock_config_zone(SHA204_HOST_ADDRESS);
#endif

	// Put client device to sleep.
	sha204p_sleep();
	
	return ret_code;
}


/** \brief This function serves as an authentication example 
 *         using the SHA204 MAC and CheckMac commands.
 *
 *         In an infinite loop, it issues the same command
 *         sequence using the sha204m_execute command of the
 *         Command Marshaling layer of the ATSHA204 library.

The command sequence wakes up the device, issues a MAC command in mode 0
using the Command Marshaling layer, puts the device to sleep, and verifies the MAC
(fixed challenge / response). Then it wakes up the same
(SHA204_CLIENT_ADDRESS == SHA204_HOST_ADDRESS) or a second device, issues
a CheckMac command supplying data obtained from the previous MAC command, verifies
the response status byte, and puts the device to sleep.
 * \return status of the operation
 */
uint8_t sha204e_checkmac_device(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;

	uint8_t i;
	uint8_t comparison_result;
	
	// Make the command buffer the size of the CheckMac command.
	static uint8_t command[CHECKMAC_COUNT];

	// Make the response buffer the size of a MAC response.
	static uint8_t response_mac[MAC_RSP_SIZE];
	
	// First four bytes of Mac command are needed for CheckMac command.
	static uint8_t other_data[CHECKMAC_OTHER_DATA_SIZE];
	
	// CheckMac response buffer
	static uint8_t response_checkmac[CHECKMAC_RSP_SIZE];

   // expected MAC response in mode 0
	static const uint8_t mac_mode0_response_expected[MAC_RSP_SIZE] =
	{
		MAC_RSP_SIZE,                                   // count
		0x06, 0x67, 0x00, 0x4F, 0x28, 0x4D, 0x6E, 0x98,
		0x62, 0x04, 0xF4, 0x60, 0xA3, 0xE8, 0x75, 0x8A,
		0x59, 0x85, 0xA6, 0x79, 0x96, 0xC4, 0x8A, 0x88,
		0x46, 0x43, 0x4E, 0xB3, 0xDB, 0x58, 0xA4, 0xFB,
		0xE5, 0x73                                       // CRC
	};

	// data for challenge in MAC mode 0 command
	const uint8_t challenge[MAC_CHALLENGE_SIZE] = {
		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
		0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
		0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
	};

	// Initialize the hardware interface.
	// Depending on which interface you have linked the
	// library to, it initializes SWI UART, SWI GPIO, or I2C.
	sha204p_init();

	while (1) {
		// If you put a break point here you will see the last
		// status response after every iteration.
		// 0x04 0x00 0x03 0x40 indicates that the last command succeeded
		// which is the CheckMac command.
		ret_code = sha204e_wakeup_device(SHA204_CLIENT_ADDRESS);
		if (ret_code != SHA204_SUCCESS)
			return ret_code;

		// Mac command with mode = 0.
		memset(response_mac, 0, sizeof(response_mac));
		ret_code = sha204m_execute(SHA204_MAC, MAC_MODE_CHALLENGE, SHA204_KEY_ID, sizeof(challenge), (uint8_t *) challenge,
					0, NULL, 0, NULL, sizeof(command), command, sizeof(response_mac), response_mac);
		// Put client device to sleep.
		sha204p_sleep();
		if (ret_code != SHA204_SUCCESS)
			continue;

		// Compare returned MAC with expected one. 
		// Make this loop resistant against a timing attack.
		comparison_result = 0;
		for (i = 0; i < sizeof(response_mac); i++)
			comparison_result |= (response_mac[i] ^ mac_mode0_response_expected[i]);
		ret_code = (comparison_result ? SHA204_GEN_FAIL : SHA204_SUCCESS);

		// Now check the MAC using the CheckMac command.
		// Put a break point below if you like to see the result of the comparison above.
		ret_code = sha204e_wakeup_device(SHA204_HOST_ADDRESS);
		if (ret_code != SHA204_SUCCESS)
			return ret_code;

		// CheckMac command with mode = 0.
		// Use the wakeup_response buffer for the CheckMac response.
		memset(response_checkmac, 0, sizeof(response_checkmac));
		// Copy Mac command byte 1 to 5 (op-code, param1, param2) to other_data.
		memcpy(other_data, &command[SHA204_OPCODE_IDX], CHECKMAC_CLIENT_COMMAND_SIZE);
		// Set the remaining nine bytes of other_data to 0.
		memset(&other_data[CHECKMAC_CLIENT_COMMAND_SIZE - 1], 0, sizeof(other_data) - CHECKMAC_CLIENT_COMMAND_SIZE);
		ret_code = sha204m_execute(
					SHA204_CHECKMAC, CHECKMAC_MODE_CHALLENGE, SHA204_KEY_ID, 
					sizeof(challenge), (uint8_t *) challenge, 
					CHECKMAC_CLIENT_RESPONSE_SIZE, &response_mac[SHA204_BUFFER_POS_DATA], 
					sizeof(other_data), other_data, 
					sizeof(command), command, sizeof(response_checkmac), response_checkmac);

		// Put host device to sleep. Put a breakpoint here to inspect the CheckMac response.
		sha204p_sleep();
		
		// Status byte = 0 means success. This line serves only a debug purpose.
		// For newer GCC's, this is not a safe spot to put a break point.
		ret_code = sha204e_check_response_status(ret_code, response_checkmac);
	}

	return ret_code;
}
#endif
extern bit ScalerMcuIICWriteStart(BYTE ucSlaveAddr, BYTE ucSubAddrLength, WORD usSubAddr);
BYTE sha204c_wakeup(BYTE *response)
{
	BYTE ret_code;// = sha204p_wakeup();
	#if 0//(_SW_IIC_SUPPORT == _ON)
		PCB_SW_IIC_SDA_CLR();	
		Delay5us(1000);//200);
	    PCB_SW_IIC_SDA_SET();
	#else
        /*ScalerSetBit(0x1030, ~(_BIT7 | _BIT2 | _BIT1 | _BIT0), (BYTE)2); // Page 10-30[2:0], Pin_198
        ScalerSetByte(0x1031, (BYTE)2); // Page 10-31[2:0], Pin_199
        bSWIIC_AB_SDA = _FALSE;       
		Delay5us(1000);//200);
        bSWIIC_AB_SDA = _TRUE;*/
	    ret_code = UserCommonIICWrite(0x00, 0, 0, 1, pIICArray, _IIC_SW_BUS, _IIC_HW_PIN, _WRITE_SIZE_8);
    	pIICArray[0] = 0xFF;
    	Delay5us(1000);
	    ret_code = UserCommonIICWrite(0xFF, 0xFF, 0, 1, pIICArray, _IIC_SW_BUS, _IIC_HW_PIN, _WRITE_SIZE_8);
	    //DebugMessageOsd("wakeup = ",ret_code);
	#endif
    ScalerTimerDelayXms(5);

	//if (ret_code != SHA204_SUCCESS)
	//	return ret_code;
	//ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
    
    ret_code = UserCommonIICRead(_SHA204_ADDRESS, 0x00, 1, 4, response, _IIC_SW_BUS, _IIC_HW_PIN);
    //ret_code = ScalerMcuIICRead(0xc8, 1, 0x00, 4, response);
    DebugMessageOsd("wakeup = ",ret_code);
    // Write Slave address and Sub-address
    //ret_code = ScalerMcuIICWriteStart(0xc8, 1, 0x00);
    {
        //return _FAIL;
    }

    /*ScalerDebugMessage("response", response[0]);
    ScalerDebugMessage("response 1", response[1]);
    ScalerDebugMessage("response 2", response[2]);
    ScalerDebugMessage("response 3", response[3]);*/
	//ret_code = UserCommonEepromIICRead(0xc8, 0x00, 1, 4, response, _IIC_SYS_EEPROM, _PCB_SYS_EEPROM_IIC);//sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
	if (ret_code != _SUCCESS)
	{
	
	    ScalerTimerDelayXms(100);
		return ret_code;
	}
	// Verify status response.
	/*if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN)
		ret_code = SHA204_INVALID_SIZE;
	else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP)
		ret_code = SHA204_COMM_FAIL;
	else {
		if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
					|| (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43))
			ret_code = SHA204_BAD_CRC;
	}
	*/
	//if (ret_code != _SUCCESS)
		//ScalerTimerDelayXms(SHA204_COMMAND_EXEC_MAX);

	return ret_code;
}


uint8_t sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2,
		uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3,
		uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer)
{
#if 1//def SHA204_CHECK_PARAMETERS

	uint8_t len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN;
	if (!tx_buffer || (tx_size < len) || (rx_size < SHA204_RSP_SIZE_MIN) || !rx_buffer)
		return SHA204_BAD_PARAM;

	if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3))
		return SHA204_BAD_PARAM;
    param2 = param2;

	// Check parameters depending on op-code.
	switch (op_code) {
	case SHA204_GENDIG:
		if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA))
			// param1 has to be GENDIG_ZONE_CONFIG.
			return SHA204_BAD_PARAM;
		break;

	case SHA204_NONCE:
		if (!data1 || (param1 > NONCE_MODE_PASSTHROUGH)	|| (param1 == NONCE_MODE_INVALID))
			// data1 cannot be null.
			// param1 has to match an allowed Nonce mode.
			return SHA204_BAD_PARAM;
		break;
		
    case SHA204_MAC:
        if ((param1 & ~MAC_MODE_MASK)
                    || (!(param1 & MAC_MODE_BLOCK2_TEMPKEY) && !data1))
            // param1 has to match an allowed MAC mode.
            // If the MAC mode requires challenge data, data1 should not be null.
            return SHA204_BAD_PARAM;
        break;

	default:
		// unknown op-code
		return SHA204_BAD_PARAM;
	}
#endif

	return SHA204_SUCCESS;
}

static uint8_t sha204p_i2c_send(uint8_t word_address, uint8_t count, uint8_t *buffer)
{
	uint8_t i2c_status;// = sha204p_send_slave_address(I2C_WRITE);
    /*i2c_status = ScalerMcuIICWriteStart(0xc8, 1, word_address);
    
	if (i2c_status != _SUCCESS)
		return SHA204_COMM_FAIL;

	if(count == 0)
	{
		if (i2c_status != _SUCCESS)
			return SHA204_COMM_FAIL;
		else
			return SHA204_SUCCESS;
	}
	i2c_status = i2c_send_bytes(count, buffer);*/
    DebugMessageOsd("count = ",count);    
    DebugMessageOsd("word_address = ",word_address);
    i2c_status = UserCommonIICWrite(_SHA204_ADDRESS, word_address, 1, count, buffer, _IIC_SW_BUS, _IIC_HW_PIN,_WRITE_SIZE_32);
	//i2c_status = ScalerMcuIICWrite(0xc8, 1, word_address, count, buffer);
	
    //DebugMessageOsd("count = ",count);
    DebugMessageOsd("i2c send status = ",i2c_status);
	/*if (i2c_status != I2C_FUNCTION_RETCODE_SUCCESS)
		return SHA204_COMM_FAIL;

	i2c_status = i2c_send_bytes(1, &word_address);
	if (i2c_status != I2C_FUNCTION_RETCODE_SUCCESS)
		return SHA204_COMM_FAIL;

	if (count == 0) {
		// We are done for packets that are not commands (Sleep, Idle, Reset).
		(void) i2c_send_stop();
		return SHA204_SUCCESS;
	}

	i2c_status = i2c_send_bytes(count, buffer);

	(void) i2c_send_stop();
*/
	if (i2c_status != _SUCCESS)
		return SHA204_COMM_FAIL;
	else
		return SHA204_SUCCESS;
}

uint8_t sha204p_send_command(uint8_t count, uint8_t *command)
{
	return sha204p_i2c_send(SHA204_I2C_PACKET_FUNCTION_NORMAL, count, command);
}
/** \brief This function resets the I/O buffer of the device.
 * \return status of the operation
 */
uint8_t sha204p_reset_io(void)
{
	return sha204p_i2c_send(SHA204_I2C_PACKET_FUNCTION_RESET, 1, NULL);
}

uint8_t sha204p_resync(uint8_t size, uint8_t *response)
{
	uint8_t nine_clocks = 0xFF;
	uint8_t ret_code ;//= i2c_send_start();
	size = size;
	response =response;
	#if 0//(_SW_IIC_SUPPORT == _ON)
		ScalerMcuIICStart(0xff);
		Delay5us(600);
		ret_code = ScalerMcuIICStart(_SHA204_SLAVE_ADDRESS);
		
	    ScalerMcuIICStop();
		if(ret_code != _SUCCESS)
		{
	        DebugMessageOsd("sha204p_resync = ",ret_code);
			return ret_code;
		}	
	#else
	    pIICArray[0] = 0xff;
	    
	    ret_code = UserCommonIICWrite(0xff, 0xff, 0, 1, pIICArray, _IIC_SW_BUS, _IIC_HW_PIN,_WRITE_SIZE_32);
	    //ret_code = UserCommonIICWriteData(0xff, 0x00, 1, pIICArray, 0, _IIC_HW_PIN);
		Delay5us(600);
		
	    pIICArray[0] = 0xFF;
	    //ret_code = UserCommonIICWriteData(_SHA204_ADDRESS, 0x00, 1, pIICArray, 0, _IIC_HW_PIN);
	    ret_code = UserCommonIICWrite(_SHA204_ADDRESS, 0x00, 0,1, pIICArray, _IIC_SW_BUS, _IIC_HW_PIN,_WRITE_SIZE_32);
		if (ret_code != _SUCCESS)
		{
	        DebugMessageOsd("sha204p_resync = ",ret_code);
			return ret_code;
		}
	#endif
	
/*	// Do not evaluate the return code that most likely indicates error,
	// since nine_clocks is unlikely to be acknowledged.
	(void) i2c_send_bytes(1, &nine_clocks);

	// Send another Start. The function sends also one byte,
	// the I2C address of the device, because I2C specification
	// does not allow sending a Stop right after a Start condition.
	ret_code = sha204p_send_slave_address(I2C_READ);

	// Send only a Stop if the above call succeeded.
	// Otherwise the above function has sent it already.
	if (ret_code == I2C_FUNCTION_RETCODE_SUCCESS)
		ret_code = i2c_send_stop();

	// Return error status if we failed to re-sync.
	if (ret_code != I2C_FUNCTION_RETCODE_SUCCESS)
		return SHA204_COMM_FAIL;
*/
	// Try to send a Reset IO command if re-sync succeeded.
	return sha204p_reset_io();
}

uint8_t sha204c_resync(uint8_t size, uint8_t *response)
{
	// Try to re-synchronize without sending a Wake token
	// (step 1 of the re-synchronization process).
	uint8_t ret_code = sha204p_resync(size, response);
	if (ret_code == SHA204_SUCCESS)
		return ret_code;
    //ScalerDebugMessage("sha204c_resync", 0x00);

	// We lost communication. Send a Wake pulse and try
	// to receive a response (steps 2 and 3 of the
	// re-synchronization process).
	//(void) sha204p_sleep();
	ret_code = sha204c_wakeup(response);

	// Translate a return value of success into one
	// that indicates that the device had to be woken up
	// and might have lost its TempKey.
	return (ret_code == _SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
}
/** \brief This function receives a response from the device.
 *
 * \param[in] size size of rx buffer
 * \param[out] response pointer to rx buffer
 * \return status of the operation
 */
uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
{
	uint8_t count;

	// Address the device and indicate that bytes are to be read.
	uint8_t i2c_status;// = sha204p_send_slave_address(I2C_READ);
	
	#if 0//(_SW_IIC_SUPPORT == _ON)
    i2c_status = ScalerMcuIICStart(0xc8|_READ);
	if (i2c_status != _SUCCESS) {
		// Translate error so that the Communication layer
		// can distinguish between a real error or the
		// device being busy executing a command.
		//if (i2c_status == I2C_FUNCTION_RETCODE_NACK)
			i2c_status = _FAIL;//SHA204_RX_NO_RESPONSE;

		return i2c_status;
	}
	
    i2c_status = i2c_receive_bytes(size, response);
	#else
    	DebugMessageOsd("size = ",size);
    	i2c_status = UserCommonIICRead(_SHA204_ADDRESS, 0x00, 0, size, response, _IIC_SW_BUS, _IIC_HW_PIN);//_PCB_SHA204_IIC);
	#endif
	
    DebugMessageOsd("response = ",*response);
    DebugMessageOsd("response = ",*(response+1));
    DebugMessageOsd("response = ",*(response+2));
    
	if (i2c_status != _SUCCESS) {
		// Translate error so that the Communication layer
		// can distinguish between a real error or the
		// device being busy executing a command.
		//if (i2c_status == I2C_FUNCTION_RETCODE_NACK)
			i2c_status = _FAIL;//SHA204_RX_NO_RESPONSE;

		return i2c_status;
	}

    //i2c_status = ScalerMcuIICRead(0xc8, 1, 0x00, 4, response);

	// Receive count byte.
	//i2c_status = i2c_receive_byte(response);
	//if (i2c_status != I2C_FUNCTION_RETCODE_SUCCESS)
		//return SHA204_COMM_FAIL;

	count = response[SHA204_BUFFER_POS_COUNT];
	if ((count < SHA204_RSP_SIZE_MIN) || (count > size)) {
		//(void) i2c_send_stop();
		return SHA204_INVALID_SIZE;
	}		
    //i2c_status = ScalerMcuIICRead(0xc8, 1, 0x00, count - 1, &response[SHA204_BUFFER_POS_DATA]);

	//i2c_status = i2c_receive_bytes(count - 1, &response[SHA204_BUFFER_POS_DATA]);

	if (i2c_status != _SUCCESS)
		return SHA204_COMM_FAIL;
	else
		return SHA204_SUCCESS;
}
uint8_t sha204c_check_crc(uint8_t *response)
{
	uint8_t crc[SHA204_CRC_SIZE];
	uint8_t count = response[SHA204_BUFFER_POS_COUNT];
//	uint8_t i;
	/*for(i = 0;i<count;i++)
	{
        ScalerDebugMessage("response[count]", response[i]);

	}*/
	count -= SHA204_CRC_SIZE;
	sha204c_calculate_crc(count, response, crc);
    //ScalerDebugMessage("count", count);
    
    //ScalerDebugMessage("response[0]", response[0]);
    //ScalerDebugMessage("response[count]", response[count]);
    //ScalerDebugMessage("response[count+1]", response[count+1]);
    //ScalerDebugMessage("crc[0]", crc[0]);
    //ScalerDebugMessage("crc[1]", crc[1]);

	return (crc[0] == response[count] && crc[1] == response[count + 1])
		? SHA204_SUCCESS : SHA204_BAD_CRC;
}

/** \brief This function runs a communication sequence.
 *
 * Append CRC to tx buffer, send command, delay, and verify response after receiving it.
 *
 * The first byte in tx buffer must be the byte count of the packet.
 * If CRC or count of the response is incorrect, or a command byte did not get acknowledged
 * (I<SUP>2</SUP>), this function requests the device to resend the response.
 * If the response contains an error status, this function resends the command.
 *
 * \param[in] tx_buffer pointer to command
 * \param[in] rx_size size of response buffer
 * \param[out] rx_buffer pointer to response buffer
 * \param[in] execution_delay Start polling for a response after this many ms.
 * \param[in] execution_timeout polling timeout in ms
 * \return status of the operation
 */
uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
			uint8_t execution_delay, uint8_t execution_timeout)
{
	uint8_t ret_code = SHA204_FUNC_FAIL;
	uint8_t ret_code_resync;
	uint8_t n_retries_send;
	uint8_t n_retries_receive;
	uint8_t i;
	uint8_t status_byte;
	uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT];
	uint8_t count_minus_crc = count - SHA204_CRC_SIZE;
	uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT;
	volatile uint16_t timeout_countdown;

	// Append CRC.
	sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc);

	// Retry loop for sending a command and receiving a response.
	n_retries_send = SHA204_RETRY_COUNT + 1;

	while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) {

		// Send command.
		ret_code = sha204p_send_command(count, tx_buffer);
		if (ret_code != SHA204_SUCCESS) {
			if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
				// The device seems to be dead in the water.
				return ret_code;
			else
				continue;
		}

		// Wait minimum command execution time and then start polling for a response.
		ScalerTimerDelayXms(execution_delay);

		// Retry loop for receiving a response.
		n_retries_receive = SHA204_RETRY_COUNT + 1;
		while (n_retries_receive-- > 0) {

			// Reset response buffer.
			for (i = 0; i < rx_size; i++)
				rx_buffer[i] = 0;

			// Poll for response.
			timeout_countdown = execution_timeout_us;
			
            //ScalerTimerDelayXms(30);//2.5);
            //ScalerDebugMessage("rx_size", rx_size);
			do {
				ret_code = sha204p_receive_response(rx_size, rx_buffer);
				timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
			} while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));

			if (ret_code == SHA204_RX_NO_RESPONSE) {
				// We did not receive a response. Re-synchronize and send command again.
				if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
					// The device seems to be dead in the water.
					return ret_code;
				else
					break;
			}

			// Check whether we received a valid response.
			if (ret_code == SHA204_INVALID_SIZE) {
				// We see 0xFF for the count when communication got out of sync.
				ret_code_resync = sha204c_resync(rx_size, rx_buffer);
				if (ret_code_resync == SHA204_SUCCESS)
					// We did not have to wake up the device. Try receiving response again.
					continue;
				if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
					// We could re-synchronize, but only after waking up the device.
					// Re-send command.
					break;
				else
					// We failed to re-synchronize.
					return ret_code;
			}

			// We received a response of valid size.
			// Check the consistency of the response.
			ret_code = sha204c_check_crc(rx_buffer);
			if (ret_code == SHA204_SUCCESS) {
				// Received valid response.
				if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN)
					// Received non-status response. We are done.
					return ret_code;

				// Received status response.
				status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];

				// Translate the three possible device status error codes
				// into library return codes.
				if (status_byte == SHA204_STATUS_BYTE_PARSE)
					return SHA204_PARSE_ERROR;
				if (status_byte == SHA204_STATUS_BYTE_EXEC)
					return SHA204_CMD_FAIL;
				if (status_byte == SHA204_STATUS_BYTE_COMM) {
					// In case of the device status byte indicating a communication
					// error this function exits the retry loop for receiving a response
					// and enters the overall retry loop
					// (send command / receive response).
					ret_code = SHA204_STATUS_CRC;
					break;
				}

				// Received status response from CheckMAC, DeriveKey, GenDig,
				// Lock, Nonce, Pause, UpdateExtra, or Write command.
				return ret_code;
			}

			else {
				// Received response with incorrect CRC.
				ret_code_resync = sha204c_resync(rx_size, rx_buffer);
				if (ret_code_resync == SHA204_SUCCESS)
					// We did not have to wake up the device. Try receiving response again.
					continue;
				if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
					// We could re-synchronize, but only after waking up the device.
					// Re-send command.
					break;
				else
					// We failed to re-synchronize.
					return ret_code;
			} // block end of check response consistency

		} // block end of receive retry loop

	} // block end of send and receive retry loop

	return ret_code;
}


/** \brief This function creates a command packet, sends it, and receives its response.
 *
 * \param[in] op_code command op-code
 * \param[in] param1 first parameter
 * \param[in] param2 second parameter
 * \param[in] datalen1 number of bytes in first data block
 * \param[in] data1 pointer to first data block
 * \param[in] datalen2 number of bytes in second data block
 * \param[in] data2 pointer to second data block
 * \param[in] datalen3 number of bytes in third data block
 * \param[in] data3 pointer to third data block
 * \param[in] tx_size size of tx buffer
 * \param[in] tx_buffer pointer to tx buffer
 * \param[in] rx_size size of rx buffer
 * \param[out] rx_buffer pointer to rx buffer
 * \return status of the operation
 */
uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
			uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3,
			uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer)
{
	uint8_t poll_delay, poll_timeout, response_size;
	uint8_t *p_buffer;
	uint8_t len;

	// Define SHA204_CHECK_PARAMETERS to compile and link this feature.
	uint8_t ret_code = sha204m_check_parameters(op_code, param1, param2,
				datalen1, data1, datalen2, data2, datalen3, data3, 
				tx_size, tx_buffer, rx_size, rx_buffer);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	// Supply delays and response size.
	switch (op_code) {

	case SHA204_GENDIG:
		poll_delay = GENDIG_DELAY;
		poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
		response_size = GENDIG_RSP_SIZE;
		break;

	case SHA204_NONCE:
		poll_delay = NONCE_DELAY;
		poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY;
		response_size = param1 == NONCE_MODE_PASSTHROUGH
							? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG;
		break;

	case SHA204_MAC:
		poll_delay = MAC_DELAY;
		poll_timeout = MAC_EXEC_MAX - MAC_DELAY;
		response_size = MAC_RSP_SIZE;
		break;

	default:
		poll_delay = 0;
		poll_timeout = SHA204_COMMAND_EXEC_MAX;
		response_size = rx_size;
		break;
	}

	// Assemble command.
	len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN;
	p_buffer = tx_buffer;
	*p_buffer++ = len;
	*p_buffer++ = op_code;
	*p_buffer++ = param1;
	*p_buffer++ = param2 & 0xFF;
	*p_buffer++ = param2 >> 8;

	if (datalen1 > 0) {
		memcpy(p_buffer, data1, datalen1);
		p_buffer += datalen1;
	}
	if (datalen2 > 0) {
		memcpy(p_buffer, data2, datalen2);
		p_buffer += datalen2;
	}
	if (datalen3 > 0) {
		memcpy(p_buffer, data3, datalen3);
		p_buffer += datalen3;
	}

	sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer);
	//for(i = 0;i<10;i++)
    //ScalerDebugMessage("tx_buffer[i]", tx_buffer[i]);

	// Send command and receive response.
	return sha204c_send_and_receive(&tx_buffer[0], response_size,
				&rx_buffer[0],	poll_delay, poll_timeout);
}
/** \brief This function puts the device into idle state.
 * \return status of the operation
 */
uint8_t sha204p_idle(void)
{
	return sha204p_i2c_send(SHA204_I2C_PACKET_FUNCTION_IDLE, 1, NULL);
}
/*
void sha204h_calculate_sha256(int32_t len, uint8_t *message, uint8_t *digest)
{
	int32_t j, swap_counter, len_mod = len % sizeof(int32_t);
	uint32_t i, w_index;
	int32_t message_index = 0;
	uint32_t padded_len = len + 8; // 8 bytes for bit length
	uint32_t bit_len = len * 8;
	uint32_t s0, s1;
	uint32_t t1, t2;
	uint32_t maj, ch;
	uint32_t word_value;
	uint32_t rotate_register[8];

	union {
		uint32_t w_word[SHA256_BLOCK_SIZE];
		uint8_t w_byte[SHA256_BLOCK_SIZE * sizeof(int32_t)];
	} w_union;

	uint32_t hash[] = {
		0x6a09e667, 0xbb67ae85, 0x3c6ef372,	0xa54ff53a,
		0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
	};

	const uint32_t code k[] = {
		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
	};

	// Process message.
	while (message_index <= padded_len) {

		// Break message into 64-byte blocks.
		w_index = 0;
		do {
			// Copy message chunk of four bytes (size of integer) into compression array.
			if (message_index < (len - len_mod)) {
				for (swap_counter = sizeof(int32_t) - 1; swap_counter >= 0; swap_counter--)
					// No padding needed. Swap four message bytes to chunk array.
					w_union.w_byte[swap_counter + w_index] = message[message_index++];

				w_index += sizeof(int32_t);
			}
			else {
				// We reached last complete word of message {len - (len mod 4)}.
				// Swap remaining bytes if any, append '1' bit and pad remaining
				// bytes of the last word.
				for (swap_counter = sizeof(int32_t) - 1;
						swap_counter >= sizeof(int32_t) - len_mod; swap_counter--)
					w_union.w_byte[swap_counter + w_index] = message[message_index++];
				w_union.w_byte[swap_counter + w_index] = 0x80;
				for (swap_counter--; swap_counter >= 0; swap_counter--)
					w_union.w_byte[swap_counter + w_index] = 0;

				// Switch to word indexing.
				w_index += sizeof(int32_t);
				w_index /= sizeof(int32_t);

				// Pad last block with zeros to a block length % 56 = 0
				// and pad the four high bytes of "len" since we work only
				// with integers and not with long integers.
				while (w_index < 15)
					 w_union.w_word[w_index++] = 0;
				// Append original message length as 32-bit integer.
				w_union.w_word[w_index] = bit_len;
				// Indicate that the last block is being processed.
				message_index += SHA256_BLOCK_SIZE;
				// We are done with pre-processing last block.
				break;
			}
		} while (message_index % SHA256_BLOCK_SIZE);
		// Created one block.

		w_index = 16;
		while (w_index < SHA256_BLOCK_SIZE) {
			// right rotate for 32-bit variable in C: (value >> places) | (value << 32 - places)
			word_value = w_union.w_word[w_index - 15];
			s0 = rotate_right(word_value, 7) ^ rotate_right(word_value, 18) ^ (word_value >> 3);

			word_value = w_union.w_word[w_index - 2];
			s1 = rotate_right(word_value, 17) ^ rotate_right(word_value, 19) ^ (word_value >> 10);

			w_union.w_word[w_index] = w_union.w_word[w_index - 16] + s0 + w_union.w_word[w_index - 7] + s1;

			w_index++;
		}

		// Initialize hash value for this chunk.
		for (i = 0; i < 8; i++)
			rotate_register[i] = hash[i];

		// hash calculation loop
		for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
			s0 = rotate_right(rotate_register[0], 2)
				^ rotate_right(rotate_register[0], 13)
				^ rotate_right(rotate_register[0], 22);
			maj = (rotate_register[0] & rotate_register[1])
				^ (rotate_register[0] & rotate_register[2])
				^ (rotate_register[1] & rotate_register[2]);
			t2 = s0 + maj;
			s1 = rotate_right(rotate_register[4], 6)
				^ rotate_right(rotate_register[4], 11)
				^ rotate_right(rotate_register[4], 25);
			ch =  (rotate_register[4] & rotate_register[5])
				^ (~rotate_register[4] & rotate_register[6]);
			t1 = rotate_register[7] + s1 + ch + k[i] + w_union.w_word[i];

			rotate_register[7] = rotate_register[6];
			rotate_register[6] = rotate_register[5];
			rotate_register[5] = rotate_register[4];
			rotate_register[4] = rotate_register[3] + t1;
			rotate_register[3] = rotate_register[2];
			rotate_register[2] = rotate_register[1];
			rotate_register[1] = rotate_register[0];
			rotate_register[0] = t1 + t2;
		}

	    // Add the hash of this block to current result.
		for (i = 0; i < 8; i++)
			hash[i] += rotate_register[i];
	}

	// All blocks have been processed.
	// Concatenate the hashes to produce digest, MSB of every hash first.
	for (i = 0; i < 8; i++) {
		for (j = sizeof(int32_t) - 1; j >= 0; j--, hash[i] >>= 8)
			digest[i * sizeof(int32_t) + j] = hash[i] & 0xFF;
	}
}*/
void sha204h_calculate_sha256(int32_t len, uint8_t *message, uint8_t *digest)
{
    int32_t j, swap_counter, len_mod = len % sizeof(int32_t);
    uint32_t i, w_index;
    int32_t message_index = 0;
    uint32_t padded_len = len + 8; // 8 bytes for bit length
    uint32_t bit_len = len * 8;
    uint32_t s0, s1;
    uint32_t t1, t2;
    uint32_t maj, ch;
    uint32_t word_value;
    uint32_t rotate_register[8];

    union {
        uint32_t w_word[SHA256_BLOCK_SIZE];
        uint8_t w_byte[SHA256_BLOCK_SIZE * sizeof(int32_t)];
    } w_union;

    uint32_t hash[] = {
        0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
        0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
    };

    const uint32_t code k[] = {
        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    };

    // Process message.
    while (message_index <= padded_len) {

        // Break message into 64-byte blocks.
        w_index = 0;
        do {
            // Copy message chunk of four bytes (size of integer) into compression array.
            if (message_index < (len - len_mod)) {
                for (swap_counter = 0; swap_counter < sizeof(int32_t); swap_counter++)
                    // No padding needed. Swap four message bytes to chunk array.
                    w_union.w_byte[swap_counter + w_index] = message[message_index++];

                w_index += sizeof(int32_t);
            }
            else {
                // We reached last complete word of message {len - (len mod 4)}.
                // Swap remaining bytes if any, append '1' bit and pad remaining
                // bytes of the last word.
                for (swap_counter = 0;
                        swap_counter < len_mod; swap_counter++)
                    w_union.w_byte[swap_counter + w_index] = message[message_index++];
                w_union.w_byte[swap_counter + w_index] = 0x80;
                for (swap_counter++; swap_counter < sizeof(int32_t); swap_counter++)
                    w_union.w_byte[swap_counter + w_index] = 0;

                // Switch to word indexing.
                w_index += sizeof(int32_t);
                w_index /= sizeof(int32_t);

                // Pad last block with zeros to a block length % 56 = 0
                // and pad the four high bytes of "len" since we work only
                // with integers and not with long integers.
                while (w_index < 15)
                     w_union.w_word[w_index++] = 0;
                // Append original message length as 32-bit integer.
                w_union.w_word[w_index] = bit_len;
                // Indicate that the last block is being processed.
                message_index += SHA256_BLOCK_SIZE;
                // We are done with pre-processing last block.
                break;
            }
        } while (message_index % SHA256_BLOCK_SIZE);
        // Created one block.

        w_index = 16;
        while (w_index < SHA256_BLOCK_SIZE) {
            // right rotate for 32-bit variable in C: (value >> places) | (value << 32 - places)
            word_value = w_union.w_word[w_index - 15];
            s0 = rotate_right(word_value, 7) ^ rotate_right(word_value, 18) ^ (word_value >> 3);

            word_value = w_union.w_word[w_index - 2];
            s1 = rotate_right(word_value, 17) ^ rotate_right(word_value, 19) ^ (word_value >> 10);

            w_union.w_word[w_index] = w_union.w_word[w_index - 16] + s0 + w_union.w_word[w_index - 7] + s1;

            w_index++;
        }

        // Initialize hash value for this chunk.
        for (i = 0; i < 8; i++)
            rotate_register[i] = hash[i];

        // hash calculation loop
        for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
            s0 = rotate_right(rotate_register[0], 2)
                ^ rotate_right(rotate_register[0], 13)
                ^ rotate_right(rotate_register[0], 22);
            maj = (rotate_register[0] & rotate_register[1])
                ^ (rotate_register[0] & rotate_register[2])
                ^ (rotate_register[1] & rotate_register[2]);
            t2 = s0 + maj;
            s1 = rotate_right(rotate_register[4], 6)
                ^ rotate_right(rotate_register[4], 11)
                ^ rotate_right(rotate_register[4], 25);
            ch =  (rotate_register[4] & rotate_register[5])
                ^ (~rotate_register[4] & rotate_register[6]);
            t1 = rotate_register[7] + s1 + ch + k[i] + w_union.w_word[i];

            rotate_register[7] = rotate_register[6];
            rotate_register[6] = rotate_register[5];
            rotate_register[5] = rotate_register[4];
            rotate_register[4] = rotate_register[3] + t1;
            rotate_register[3] = rotate_register[2];
            rotate_register[2] = rotate_register[1];
            rotate_register[1] = rotate_register[0];
            rotate_register[0] = t1 + t2;
        }

        // Add the hash of this block to current result.
        for (i = 0; i < 8; i++)
            hash[i] += rotate_register[i];
    }

    // All blocks have been processed.
    // Concatenate the hashes to produce digest, MSB of every hash first.
    for (i = 0; i < 8; i++) {
        for (j = sizeof(int32_t) - 1; j >= 0; j--, hash[i] >>= 8)
            digest[i * sizeof(int32_t) + j] = hash[i] & 0xFF;
    }
}

uint8_t sha204h_nonce(struct sha204h_nonce_in_out *param)
{
	uint8_t temporary[SHA204_MSG_SIZE_NONCE];
	uint8_t *p_temp;

	// Check parameters
	if (!param->temp_key || !param->num_in || (param->mode > NONCE_MODE_PASSTHROUGH) || (param->mode == NONCE_MODE_INVALID)
			|| (((param->mode == NONCE_MODE_SEED_UPDATE || (param->mode == NONCE_MODE_NO_SEED_UPDATE)) && !param->rand_out)))
		return SHA204_BAD_PARAM;

	// Calculate or pass-through the nonce to TempKey->Value
	if ((param->mode == NONCE_MODE_SEED_UPDATE) || (param->mode == NONCE_MODE_NO_SEED_UPDATE)) {
		// Calculate nonce using SHA-256 (refer to data sheet)
		p_temp = temporary;

		memcpy(p_temp, param->rand_out, NONCE_RSP_SIZE_LONG - SHA204_PACKET_OVERHEAD);
		p_temp += NONCE_RSP_SIZE_LONG - SHA204_PACKET_OVERHEAD;

		memcpy(p_temp, param->num_in, NONCE_NUMIN_SIZE);
		p_temp += NONCE_NUMIN_SIZE;

		*p_temp++ = SHA204_NONCE;
		*p_temp++ = param->mode;
		*p_temp++ = 0x00;

		// Calculate SHA256 to get the nonce
		sha204h_calculate_sha256(SHA204_MSG_SIZE_NONCE, temporary, param->temp_key->value);

		// Update TempKey->SourceFlag to 0 (random)
		param->temp_key->source_flag = 0;
	} 
	else if (param->mode == NONCE_MODE_PASSTHROUGH) {
		// Pass-through mode
		memcpy(param->temp_key->value, param->num_in, NONCE_NUMIN_SIZE_PASSTHROUGH);

		// Update TempKey->SourceFlag to 1 (not random)
		param->temp_key->source_flag = 1;
	}

	// Update TempKey fields
	param->temp_key->key_id = 0;
	param->temp_key->gen_data = 0;
	param->temp_key->check_flag = 0;
	param->temp_key->valid = 1;

	return SHA204_SUCCESS;
}
#if 0
/** \brief This function sends a Read command to the device.
 *
 * \param[in]  tx_buffer pointer to transmit buffer
 * \param[out] rx_buffer pointer to receive buffer
 * \param[in]  zone 0: Configuration; 1: OTP; 2: Data
 * \param[in]  address address to read from
 * \return status of the operation
 */
uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address)
{
	uint8_t rx_size;

	if (!tx_buffer || !rx_buffer || (zone & ~READ_ZONE_MASK)
				|| ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP)))
		// no null pointers allowed
		// zone has to match a valid param1 value.
		// Reading a 32-byte from the OTP zone is not allowed.
		return SHA204_BAD_PARAM;

	address >>= 2;
	if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) {
		if (address > SHA204_ADDRESS_MASK_CONFIG)
			return SHA204_BAD_PARAM;
	}
	else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) {
		if (address > SHA204_ADDRESS_MASK_OTP)
			return SHA204_BAD_PARAM;
	}
	else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) {
		if (address > SHA204_ADDRESS_MASK)
			return SHA204_BAD_PARAM;
	}

	tx_buffer[SHA204_COUNT_IDX] = READ_COUNT;
	tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ;
	tx_buffer[READ_ZONE_IDX] = zone;
	tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK);
	tx_buffer[READ_ADDR_IDX + 1] = 0;

	rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;

	return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0],
				/*READ_DELAY*/20, READ_EXEC_MAX - READ_DELAY);
}
uint8_t sha204e_read_config_zone(uint8_t device_id, uint8_t *config_data)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;
	
	uint16_t config_address;
	
	// Make the command buffer the size of the Read command.
	uint8_t command[READ_COUNT];

	// Make the response buffer the size of the maximum Read response.
	uint8_t response[READ_32_RSP_SIZE];
	
	// Use this buffer to read the last 24 bytes in 4-byte junks.
	uint8_t response_read_4[READ_4_RSP_SIZE];
	
	uint8_t *p_response;
	device_id = device_id;
	//sha204p_init();

	//sha204p_set_device_id(device_id);

	// Read first 32 bytes. Put a breakpoint after the read and inspect "response" to obtain the data.
	ret_code = sha204c_wakeup(response);
	if (ret_code != _SUCCESS)
		return ret_code;
		
	memset(response, 0, sizeof(response));
	config_address = 0;
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG | READ_ZONE_MODE_32_BYTES, config_address);
	//sha204p_sleep();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	if (config_data) {
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_32);
		config_data += SHA204_ZONE_ACCESS_32;
	}		
	// Read second 32 bytes. Put a breakpoint after the read and inspect "response" to obtain the data.
	memset(response, 0, sizeof(response));
	ret_code = sha204c_wakeup(response);
	
    ScalerDebugMessage("config sha204c_wakeup", ret_code);
	if (ret_code != _SUCCESS)
		return ret_code;

	config_address += SHA204_ZONE_ACCESS_32;
	memset(response, 0, sizeof(response));
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG | READ_ZONE_MODE_32_BYTES, config_address);
	//sha204p_sleep();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	if (config_data) {
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_32);
		config_data += SHA204_ZONE_ACCESS_32;
	}
		
	// Read last 24 bytes in six four-byte junks.
	memset(response, 0, sizeof(response));
	ret_code = sha204c_wakeup(response);
	
    ScalerDebugMessage("config sha204c_wakeup 2", ret_code);
	if (ret_code != _SUCCESS)
		return ret_code;
	
    ScalerDebugMessage("config_address", config_address);
	config_address += SHA204_ZONE_ACCESS_32;
	response[SHA204_BUFFER_POS_COUNT] = 0;
	p_response = &response[SHA204_BUFFER_POS_DATA];
	memset(response, 0, sizeof(response));
	while (config_address < SHA204_CONFIG_SIZE) {
		memset(response_read_4, 0, sizeof(response_read_4));
		ret_code = sha204m_read(command, response_read_4, SHA204_ZONE_CONFIG, config_address);
		if (ret_code != SHA204_SUCCESS) {
		
        ScalerDebugMessage("while sha204m_read", ret_code);
//			sha204p_sleep();
			return ret_code;
		}
		memcpy(p_response, &response_read_4[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_4);
		p_response += SHA204_ZONE_ACCESS_4;
		response[SHA204_BUFFER_POS_COUNT] += SHA204_ZONE_ACCESS_4; // Update count byte in virtual response packet.
		config_address += SHA204_ZONE_ACCESS_4;
		
        ScalerDebugMessage("config_address 1", config_address);
	}	
	// Put a breakpoint here and inspect "response" to obtain the data.
	//sha204p_sleep();
    ScalerDebugMessage("config ret_code", ret_code);
    
//    ScalerDebugMessage("config_data", config_data);
    
    ScalerDebugMessage("config_data[1]", config_data[1]);
	if (ret_code == SHA204_SUCCESS && config_data)
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_CONFIG_SIZE - 2 * SHA204_ZONE_ACCESS_32);

	return ret_code;
}
#endif
/** \brief This function combines the current TempKey with a stored value.
 
The stored value can be a data slot, OTP page, configuration zone, or hardware transport key.
The TempKey generated by this function will match with the TempKey in the device generated
when executing a GenDig command.
The TempKey should be valid (temp_key.valid = 1) before executing this function.
To use this function, an application first sends a GenDig command with a chosen stored value to the device.
This stored value must be known by the application and is passed to this GenDig calculation function.
The function calculates a new TempKey and returns it.
 
 * \param[in, out] param pointer to parameter structure
 * \return status of the operation
 */
uint8_t sha204h_gen_dig(struct sha204h_gen_dig_in_out *param)
{
	uint8_t temporary[SHA204_MSG_SIZE_GEN_DIG];
	uint8_t *p_temp;

	// Check parameters
	if (!param->stored_value || !param->temp_key
			|| ((param->zone != GENDIG_ZONE_OTP) 
				&& (param->zone != GENDIG_ZONE_DATA)
				&& (param->zone != GENDIG_ZONE_CONFIG)) 
		)
		return SHA204_BAD_PARAM;

	// Check TempKey fields validity (TempKey is always used)
	if (// TempKey.CheckFlag must be 0 and TempKey.Valid must be 1
		param->temp_key->check_flag	|| (param->temp_key->valid != 1)
		)
	{
		// Invalidate TempKey, then return
		param->temp_key->valid = 0;
		return SHA204_CMD_FAIL;
	}

	// Start calculation
	p_temp = temporary;

	// (1) 32 bytes inputKey
	//     (Config[KeyID] or OTP[KeyID] or Data.slot[KeyID] or TransportKey[KeyID])
	memcpy(p_temp, param->stored_value, SHA204_KEY_SIZE);
	p_temp += SHA204_KEY_SIZE;

	// (2) 1 byte Opcode
	*p_temp++ = SHA204_GENDIG;

	// (3) 1 byte Param1 (zone)
	*p_temp++ = param->zone;

	// (4) 2 bytes Param2 (keyID)
	*p_temp++ = param->key_id & 0xFF;
	*p_temp++ = (param->key_id >> 8) & 0xFF;

	// (5) 1 byte SN[8] = 0xEE
	*p_temp++ = SHA204_SN_8;

	// (6) 2 bytes SN[0:1] = 0x0123
	*p_temp++ = SHA204_SN_0;
	*p_temp++ = SHA204_SN_1;

	// (7) 25 zeros
	memset(p_temp, 0, SHA204_GENDIG_ZEROS_SIZE);
	p_temp += SHA204_GENDIG_ZEROS_SIZE;

	// (8) 32 bytes TempKey
	memcpy(p_temp, param->temp_key->value, SHA204_KEY_SIZE);

	// Calculate SHA256 to get the new TempKey
	sha204h_calculate_sha256(SHA204_MSG_SIZE_GEN_DIG, temporary, param->temp_key->value);

	// Update TempKey fields
	param->temp_key->valid = 1;

	if ((param->zone == GENDIG_ZONE_DATA) && (param->key_id <= 15)) {
		param->temp_key->gen_data = 1;
		param->temp_key->key_id = (param->key_id & 0xF);    // mask lower 4-bit only
	} 
	else {
		param->temp_key->gen_data = 0;
		param->temp_key->key_id = 0;
	}

	return SHA204_SUCCESS;
}
/** \brief This function copies otp and sn data into a command buffer.
 *
 * \param[in, out] param pointer to parameter structure
 * \return pointer to command buffer byte that was copied last
 */
uint8_t *sha204h_include_data(struct sha204h_include_data_in_out *param)
{
	if (param->mode & MAC_MODE_INCLUDE_OTP_88) {
		memcpy(param->p_temp, param->otp, SHA204_OTP_SIZE_8 + SHA204_OTP_SIZE_3);            // use OTP[0:10], Mode:5 is overridden
		param->p_temp += SHA204_OTP_SIZE_8 + SHA204_OTP_SIZE_3;
	}
	else {
		if (param->mode & MAC_MODE_INCLUDE_OTP_64)
			memcpy(param->p_temp, param->otp, SHA204_OTP_SIZE_8);        // use 8 bytes OTP[0:7] for (6)
		else
			memset(param->p_temp, 0, SHA204_OTP_SIZE_8);                 // use 8 zeros for (6)
		param->p_temp += SHA204_OTP_SIZE_8;

		memset(param->p_temp, 0, SHA204_OTP_SIZE_3);                     // use 3 zeros for (7)
		param->p_temp += SHA204_OTP_SIZE_3;
	}

	// (8) 1 byte SN[8] = 0xEE
	*param->p_temp++ = SHA204_SN_8;

	// (9) 4 bytes SN[4:7] or zeros
	if (param->mode & MAC_MODE_INCLUDE_SN)
		memcpy(param->p_temp, &param->sn[4], SHA204_SN_SIZE_4);          //use SN[4:7] for (9)
	else
		memset(param->p_temp, 0, SHA204_SN_SIZE_4);                      //use zeros for (9)
	param->p_temp += SHA204_SN_SIZE_4;

	// (10) 2 bytes SN[0:1] = 0x0123
	*param->p_temp++ = SHA204_SN_0;
	*param->p_temp++ = SHA204_SN_1;

	// (11) 2 bytes SN[2:3] or zeros
	if (param->mode & MAC_MODE_INCLUDE_SN)
		memcpy(param->p_temp, &param->sn[2], SHA204_SN_SIZE_2);          //use SN[2:3] for (11)
	else
		memset(param->p_temp, 0, SHA204_SN_SIZE_2);                      //use zeros for (9)
	param->p_temp += SHA204_SN_SIZE_2;
	
	return param->p_temp;
}

/** \brief This function generates an SHA-256 digest (MAC) of a key, challenge, and other information.
 
The resulting digest will match with the one generated by the device when executing a MAC command.
The TempKey (if used) should be valid (temp_key.valid = 1) before executing this function.
 
 * \param[in, out] param pointer to parameter structure
 * \return status of the operation
 */
uint8_t sha204h_mac(struct sha204h_mac_in_out *param)
{
	uint8_t temporary[SHA204_MSG_SIZE_MAC];
	uint8_t *p_temp;
	struct sha204h_include_data_in_out include_data;

		include_data.otp = param->otp;
		include_data.sn = param->sn;
		include_data.mode = param->mode;
	/*= {
		.otp = param->otp, .sn = param->sn, .mode = param->mode
	};*/
	
	// Check parameters
	if (!param->response
		|| (param->mode & ~MAC_MODE_MASK)
		|| (!(param->mode & MAC_MODE_BLOCK1_TEMPKEY) && !param->key)
		|| (!(param->mode & MAC_MODE_BLOCK2_TEMPKEY) && !param->challenge)
		|| ((param->mode & MAC_MODE_USE_TEMPKEY_MASK) && !param->temp_key)
		|| (((param->mode & MAC_MODE_INCLUDE_OTP_64) || (param->mode & MAC_MODE_INCLUDE_OTP_88)) && !param->otp)
		|| ((param->mode & MAC_MODE_INCLUDE_SN) && !param->sn)
		)
		return SHA204_BAD_PARAM;

	// Check TempKey fields validity if TempKey is used
	if (((param->mode & MAC_MODE_USE_TEMPKEY_MASK) != 0)
			// TempKey.CheckFlag must be 0 and TempKey.Valid must be 1
			&& (param->temp_key->check_flag || (param->temp_key->valid != 1)
			// If either mode parameter bit 0 or bit 1 are set, mode parameter bit 2 must match temp_key.source_flag.
			// Logical not (!) is used to evaluate the expression to TRUE / FALSE first before comparison (!=).
			|| (!(param->mode & MAC_MODE_SOURCE_FLAG_MATCH) != !(param->temp_key->source_flag)))
		)
	{
		// Invalidate TempKey, then return
		param->temp_key->valid = 0;
		return SHA204_CMD_FAIL;
	}

	// Start calculation
	p_temp = temporary;

	// (1) first 32 bytes
	memcpy(p_temp, param->mode & MAC_MODE_BLOCK1_TEMPKEY ? param->temp_key->value : param->key, SHA204_KEY_SIZE);                // use Key[KeyID]
	p_temp += SHA204_KEY_SIZE;

	// (2) second 32 bytes
	memcpy(p_temp, param->mode & MAC_MODE_BLOCK2_TEMPKEY ? param->temp_key->value : param->challenge, SHA204_KEY_SIZE);          // use Key[KeyID]
	p_temp += SHA204_KEY_SIZE;

	// (3) 1 byte opcode
	*p_temp++ = SHA204_MAC;

	// (4) 1 byte mode parameter
	*p_temp++ = param->mode;

	// (5) 2 bytes keyID
	*p_temp++ = param->key_id & 0xFF;
	*p_temp++ = (param->key_id >> 8) & 0xFF;
	
	include_data.p_temp = p_temp;
	sha204h_include_data(&include_data);

	// Calculate SHA256 to get the MAC digest
	sha204h_calculate_sha256(SHA204_MSG_SIZE_MAC, temporary, param->response);

	// Update TempKey fields
	if (param->temp_key)
		param->temp_key->valid = 0;

	return SHA204_SUCCESS;
}

/** \brief This function serves as an authentication example
 *         using the SHA204 Nonce, GenDig, and MAC commands.
 *
 *         In an infinite loop, it issues the same command
 *         sequence using the Command Marshaling layer of
 *         the ATSHA204 library.

The following command sequence wakes up the device, issues a Nonce, a GenDig, and
a MAC command using the Command Marshaling layer, and puts the device to sleep.
In parallel, it calculates in firmware the TempKey and the MAC using helper
functions located in \ref sha204_helper.c and compares the MAC command response
with the calculated result.
 * \return status of the operation
 */
uint8_t sha204e_checkmac_firmware(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;
	uint8_t i,loop_num;
	
	static uint8_t wakeup_response[4];//SHA204_RSP_SIZE_MIN];
	
	static uint8_t tx_buffer[CHECKMAC_COUNT];
	static uint8_t rx_buffer[MAC_RSP_SIZE];
		code uint8_t num_in[NONCE_NUMIN_SIZE] = {
		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
		0x30, 0x31, 0x32, 0x33
	};
	//AB DD BB 23 12 CF 55 4E 45 D4 04 01 BD 0E D3 C6 73 D3 B7 B8 2D 85 D9 F3 13 B5 5E DA 3D 94 00 00
		uint8_t key_slot_0[SHA204_KEY_SIZE] = {
		/*0x00, 0x00, 0xA1, 0xAC, 0x57, 0xFF, 0x40, 0x4E,
		0x45, 0xD4,	0x04, 0x01, 0xBD, 0x0E, 0xD3, 0xC6,
		0x73, 0xD3, 0xB7, 0xB8,	0x2D, 0x85, 0xD9, 0xF3,
		0x13, 0xB5, 0x5E, 0xDA, 0x3D, 0x94,	0x00, 0x00*/
		/*0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
		0x33, 0x33,	0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
		0x33, 0x33, 0x33, 0x33,	0x33, 0x33, 0x33, 0x33,
		0x33, 0x33, 0x33, 0x33, 0x33, 0x33,	0x33, 0x33*/
		
		/*0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
		0x11, 0x11,	0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
		0x11, 0x11, 0x11, 0x11,	0x11, 0x11, 0x11, 0x11,
		0x11, 0x11, 0x11, 0x11, 0x11, 0x11,	0x11, 0x11*/
		
        /*0xAB, 0xDD, 0xBB, 0x23, 0x12, 0xCF, 0x55, 0x4E, 
        0x45, 0xD4, 0x04, 0x01, 0xBD, 0x0E, 0xD3, 0xC6, 
        0x73, 0xD3, 0xB7, 0xB8, 0x2D, 0x85, 0xD9, 0xF3, 
        0x13, 0xB5, 0x5E, 0xDA, 0x3D, 0x94, 0x00, 0x00	*/ 
        
        /*0xBC,0x43,0xE4,0xC9,0x70,0x6E,0x1A,0xAC,
        0x74,0xD1,0x0A,0x1E,0x37,0xA0,0x43,0xB4,
        0x82,0x22,0xDB,0x88,0xD7,0x97,0x3E,0xCB,
        0x1D,0x4C,0x07,0x6E,0x27,0x1E,0x54,0x06	*/
        
        0x2A,0x1C,0x14,0x8B,0xD6,0x72,0x4D,0x26,
        0x37,0x55,0x8C,0x16,0xDE,0xA9,0x7E,0x13,
        0xB5,0x4D,0xD1,0xBE,0xF9,0xE3,0xC8,0x98,
        0x48,0x5E,0x73,0xFD,0x61,0x12,0x52,0xFD,


	};
	//uint8_t config_data[SHA204_CONFIG_SIZE];
    struct sha204h_nonce_in_out nonce_param;       //parameter for nonce helper function
	struct sha204h_gen_dig_in_out gendig_param;	//parameter for gendig helper function
	struct sha204h_temp_key tempkey;			      //tempkey parameter for nonce and mac helper function
	struct sha204h_mac_in_out mac_param;		   //parameter for mac helper function
	static uint8_t mac[CHECKMAC_CLIENT_RESPONSE_SIZE];
	uint8_t mac_mode = MAC_MODE_BLOCK1_TEMPKEY | MAC_MODE_BLOCK2_TEMPKEY;
	uint8_t comparison_result;
	/*
	struct sha204h_gen_dig_in_out gendig_param;	//parameter for gendig helper function
	static uint8_t wakeup_response[SHA204_RSP_SIZE_MIN];
	static uint8_t tx_buffer[CHECKMAC_COUNT];
	static uint8_t rx_buffer[MAC_RSP_SIZE];
	uint8_t num_in[NONCE_NUMIN_SIZE] = {
		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
		0x30, 0x31, 0x32, 0x33
	};
	uint8_t key_slot_0[SHA204_KEY_SIZE] = {
		0x00, 0x00, 0xA1, 0xAC, 0x57, 0xFF, 0x40, 0x4E,
		0x45, 0xD4,	0x04, 0x01, 0xBD, 0x0E, 0xD3, 0xC6,
		0x73, 0xD3, 0xB7, 0xB8,	0x2D, 0x85, 0xD9, 0xF3,
		0x13, 0xB5, 0x5E, 0xDA, 0x3D, 0x94,	0x00, 0x00
	};
*/
	// Initialize the hardware interface.
	// Depending on which interface you have linked the
	// library to, it initializes SWI UART, SWI GPIO, or I2C.
	//sha204p_init();
	//g_ucDelay5usN = 1;

	for(loop_num = 0;loop_num<3;loop_num++)
	//while (1) 
	{
	
	    //ScalerDebugMessage("for loop_num", loop_num);
		#if 1
		// ----------------------- Nonce --------------------------------------------
		// Wake up the device.
		// If you put a break point here you will see the last
		// status after every iteration.
		// You can also inspect the mac and rx_buffer variables which should match.
		memset(wakeup_response, 0, sizeof(wakeup_response));
		ret_code = sha204c_wakeup(wakeup_response);
		if (ret_code != _SUCCESS) {
		//	(void) sha204p_sleep();
			ret_code = SHA204_RX_NO_RESPONSE;
	        //ScalerDebugMessage("wakeup fail", ret_code);
			continue;
		}			

		
		memset(rx_buffer, 0, sizeof(rx_buffer));
		ret_code = sha204m_execute(SHA204_NONCE, NONCE_MODE_NO_SEED_UPDATE, 0, NONCE_NUMIN_SIZE, num_in, 
			0, NULL, 0, NULL, sizeof(tx_buffer), tx_buffer, sizeof(rx_buffer), rx_buffer);
        //ScalerDebugMessage("sha204m_execute", ret_code);

		if (ret_code != SHA204_SUCCESS) {
			//(void) sha204p_sleep();
			
	        //ScalerDebugMessage("NCE fail", ret_code);
			continue;
		}


		// Put device into Idle mode since the TempKey calculation in firmware might take longer
		// than the device timeout. Putting the device into Idle instead of Sleep mode
		// maintains the TempKey.
		sha204p_idle();
		
		// Calculate TempKey using helper function.
		nonce_param.mode = NONCE_MODE_NO_SEED_UPDATE;
		nonce_param.num_in = num_in;	
		nonce_param.rand_out = &rx_buffer[SHA204_BUFFER_POS_DATA];	
		nonce_param.temp_key = &tempkey;
		ret_code = sha204h_nonce(&nonce_param);
		
        //ScalerDebugMessage("sha204h_nonce", ret_code);
		if (ret_code != SHA204_SUCCESS) {
			//sha204e_wakeup_sleep();
			
	        //ScalerDebugMessage("h_NCE fail", ret_code);
			continue;
		}

		// ----------------------- GenDig --------------------------------------------
		// Wake up the device from Idle mode.
		memset(wakeup_response, 0, sizeof(wakeup_response));
		ret_code = sha204c_wakeup(wakeup_response);
		if (ret_code != _SUCCESS) {
			//(void) sha204p_sleep();
			ret_code = SHA204_RX_NO_RESPONSE;
	        //ScalerDebugMessage("wakeup 1 fail", ret_code);
			continue;
		}			

		memset(rx_buffer, 0, sizeof(rx_buffer));
		
        //ScalerDebugMessage("tx_buffer[0]", tx_buffer[0]);
        
        //ScalerDebugMessage("tx_buffer[1]", tx_buffer[1]);
		ret_code = sha204m_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, SHA204_KEY_ID, 0,
			NULL, 0, NULL, 0, NULL, sizeof(tx_buffer), tx_buffer, sizeof(rx_buffer), rx_buffer);		 
        //ScalerDebugMessage("SHA204_GENDIG", ret_code);

		if (ret_code != SHA204_SUCCESS) {
			//(void) sha204p_sleep();
	        //ScalerDebugMessage("GEN fail", ret_code);
			continue;
		}
		
        //ScalerDebugMessage("rx_buffer[1]", rx_buffer[SHA204_BUFFER_POS_STATUS]);
		// Check response status byte for error.
		if (rx_buffer[SHA204_BUFFER_POS_STATUS] != SHA204_SUCCESS) {
			//(void) sha204p_sleep();
			continue;
		}
		sha204p_idle();

		// Update TempKey using helper function.
		gendig_param.zone = GENDIG_ZONE_DATA;
		gendig_param.key_id = SHA204_KEY_ID;
		gendig_param.stored_value = key_slot_0;
		gendig_param.temp_key = &tempkey;
		ret_code = sha204h_gen_dig(&gendig_param);
		
		if (ret_code != SHA204_SUCCESS) {
		
	        //ScalerDebugMessage("gen_dig", ret_code);
			//sha204e_wakeup_sleep();
			continue;
		}

		// ----------------------- MAC --------------------------------------------
		// Wake up the device from Idle mode.
		memset(wakeup_response, 0, sizeof(wakeup_response));
		ret_code = sha204c_wakeup(wakeup_response);
		if (ret_code != _SUCCESS) {
		ret_code = SHA204_RX_NO_RESPONSE;
	        //ScalerDebugMessage("wakeup 2 fail", ret_code);
			//(void) sha204p_sleep();
			continue;
		}
		
		// Issue a MAC command with mode = 3.
		memset(rx_buffer, 0, sizeof(rx_buffer));
		ret_code = sha204m_execute(SHA204_MAC, mac_mode, SHA204_KEY_ID,
			0, NULL, 0, NULL, 0, NULL, sizeof(tx_buffer), tx_buffer, sizeof(rx_buffer), rx_buffer);		 

		// Put device to sleep.
		//sha204p_sleep();
        //ScalerDebugMessage("MC", ret_code);

		if (ret_code != SHA204_SUCCESS)
			continue;
		
		// Calculate MAC using helper function.
		mac_param.mode = mac_mode;
		mac_param.key_id = SHA204_KEY_ID;
		mac_param.challenge = NULL;
		mac_param.key = NULL;
		mac_param.otp = NULL;
		mac_param.sn = NULL;
		mac_param.response = mac;
		mac_param.temp_key = &tempkey;
		ret_code = sha204h_mac(&mac_param);
		if (ret_code != SHA204_SUCCESS)
		{
	        //ScalerDebugMessage("h_mc Fail", ret_code);
			continue;
		}
#if 1
		/*for(i = 0;i<sizeof(mac);i++)
		{
            ScalerDebugMessage("rx_buffer[i + 1]", rx_buffer[i + SHA204_BUFFER_POS_STATUS]);
            ScalerDebugMessage("mac", mac[i]);

		}*/
		// Compare the Mac response with the calculated MAC.
		// Make this loop resistant against a timing attack.
		comparison_result = 0;
		for (i = 0; i < sizeof(mac); i++)
			comparison_result |= (rx_buffer[i + SHA204_BUFFER_POS_STATUS] ^ mac[i]);

		ret_code = (comparison_result ? SHA204_GEN_FAIL : SHA204_SUCCESS);
		
        //ScalerDebugMessage("ret_code", ret_code);
        //ScalerDebugMessage("result", comparison_result);
        if(ret_code == SHA204_SUCCESS)
        	return ret_code;
	#endif
	#else
    ret_code = sha204e_read_config_zone(0xc8,config_data);
    
    ScalerDebugMessage("read_config_zone", ret_code);
    for(i = 0;i<SHA204_CONFIG_SIZE;i++)
    
    ScalerDebugMessage("config_data[i] = ", config_data[i]);

	#endif
	}

	return ret_code;
}
#if 0

/** \brief This function serves as an authentication example using the SHA204 Nonce,
 *         DeriveKey, and MAC commands for a client, and the Nonce, GenDig, and
 *         CheckMac commands for a host device.

Creating a child key on the client allows a host device to check a MAC in a highly secure
fashion. No replay attacks are possible when using a random number generated by the host
device as the challenge, SHA256 calculation in firmware is not needed, and keys are only
stored on the secure device.
 
A brief explanation for this command sequence:
The client generates a child key (DeriveKey command) derived from a parent key that it
shares with the host device, using a random nonce (commands Random and Nonce). It then
stores it in one of its key slots. The host generates the same key and stores it in its
TempKey using the same nonce. Now, when the client receives a MAC command with the child
key id, a CheckMac command on the host using the TempKey will succeed.

To run this command sequence successfully the devices have to be configured first: 
The child key has to point to the parent, and the parent key in the host device has to be
flagged as CheckOnly.

Because every time this command sequence is executed the slot for the child key is being 
written, this sequence does not run in a loop to prevent wearing out the flash.

Command sequence when using a derived key:
<ol>
<li>
	MCU to client device: fixed nonce -> TempKey
</li>
<li>
	MCU to client device: DeriveKey -> 
	child key in chosen slot (child key configuration points to parent key)
</li>
<li>
	MCU to client device: fixed nonce -> TempKey</li>
<li>
	MCU to client device: MAC -> 
	response = sha256(chosen slot  / child key, fixed nonce / TempKey, 
	                  command, 3 bytes of SN)
</li>
<li>
	MCU to host device:   GenDig -> TempKey = child key
</li>
<li>
	MCU to host device:   CheckMac -> 
	sha256(child key / TempKey, challenge / fixed nonce, MAC command, 3 bytes of SN)
</li>
</ol>
As you can see, the sha256 input values for the MAC and the CheckMac commands are the
same (child key, fixed nonce, MAC command, the three constant bytes of SN).


 * \return status of the operation
 */
uint8_t sha204e_checkmac_derived_key(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;

	static uint8_t response_random[RANDOM_RSP_SIZE];
	uint8_t *random = &response_random[SHA204_BUFFER_POS_DATA];
	
	// Make the command buffer the minimum size of the Write command.
	uint8_t command[SHA204_CMD_SIZE_MAX];

	// Make the response buffer the maximum size.
	uint8_t response_status[SHA204_RSP_SIZE_MIN];

	// MAC response buffer
	uint8_t response_mac[SHA204_RSP_SIZE_MAX];
	
	// We need this buffer for the DeriveKey, GenDig, and CheckMac command.
	uint8_t other_data[CHECKMAC_OTHER_DATA_SIZE];
	
	uint8_t command_derive_key[GENDIG_OTHER_DATA_SIZE];
	
	uint8_t command_mac[CHECKMAC_CLIENT_COMMAND_SIZE];
		
	// Initialize the hardware interface.
	// Depending on which interface you have linked the
	// library to, it initializes SWI GPIO, or I2C.
	// This example does not run when SWI UART is used.
	sha204p_init();

	ret_code = sha204e_configure_derive_key();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	ret_code = sha204c_wakeup(response_status);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
	
	/*
	Obtain a random number from host device. We can generate a random number to
	be used by a pass-through nonce (TempKey.SourceFlag = Input = 1) in whatever 
	way we want but we use the host	device because it has a high-quality random 
	number generator. We are using the host and not the client device because we 
	like to show a typical accessory authentication example where the MCU this 
	code is running on and the host device are inaccessible to an adversary, 
	whereas the client device is built into an easily accessible accessory. We 
	prevent an adversary to	mount replay attacks by supplying the pass-through
	nonce. For the same reason, we do not want to use the same pass-through 
	number every time we authenticate. The same nonce would produce the same Mac 
	response. Be aware that the Random command returns a fixed number
	(0xFFFF0000FFFF0000...) when the configuration zone of the device is not locked.
	*/
	
	sha204p_set_device_id(SHA204_HOST_ADDRESS);

	// ---------------------------------------------------------------------------
	// host: Get random number.
	// No need to update the seed because it gets updated with every wake / sleep
	// cycle anyway.
	// ---------------------------------------------------------------------------
	ret_code = sha204m_random(command, response_random, RANDOM_NO_SEED_UPDATE);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}
	
	// ---------------------------------------------------------------------------
	// client: Create child key using a random pass-through nonce. 
	// Then send a MAC command using the same nonce.
	// ---------------------------------------------------------------------------
	sha204p_set_device_id(SHA204_CLIENT_ADDRESS);

	// Send Nonce command in pass-through mode using the random number in preparation
	// for DeriveKey command. TempKey holds the random number after this command succeeded.
	ret_code = sha204m_nonce(command, response_status, NONCE_MODE_PASSTHROUGH, random);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}

	// Send DeriveKey command.
	// child key = sha256(parent key[32], DeriveKey command[4], sn[3], 0[25], TempKey[32] = random)
	ret_code = sha204m_derive_key(command, response_status, DERIVE_KEY_RANDOM_FLAG, SHA204_KEY_CHILD, NULL);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}
	
	// Copy op-code and parameters to command_derive_key to be used in subsequent GenDig and CheckMac
	// host commands.
	memcpy(command_derive_key, &command[SHA204_OPCODE_IDX], sizeof(command_derive_key));

	// Send Nonce command in preparation for MAC command.
	ret_code = sha204m_nonce(command, response_status, NONCE_MODE_PASSTHROUGH, random);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}

	// Send MAC command.
	// MAC = sha256(child key[32], TempKey[32] = random, MAC command[4], 0[11], sn8[1], 0[4], sn0_1[2], 0[2])
	// mode: first 32 bytes data slot (= child key), second 32 bytes TempKey (= random), TempKey.SourceFlag = Input
	ret_code = sha204m_mac(command, response_mac, MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_SOURCE_FLAG_MATCH, 
	                       SHA204_KEY_CHILD, NULL);
	if (ret_code != SHA204_SUCCESS) {
		sha204e_sleep();
		return ret_code;
	}

	// Save op-code and parameters to be used in the CheckMac command for the host.
	memcpy(command_mac, &command[SHA204_OPCODE_IDX], sizeof(command_mac));
		
	// Put client device to sleep.
	sha204p_sleep();
	
	// ---------------------------------------------------------------------------
	// host: Generate digest (GenDig) using a random pass-through nonce.
	// Then send a CheckMac command with the MAC response.
	// ---------------------------------------------------------------------------

	// Send Nonce command in pass-through mode using the random number in preparation
	// for GenDig command. TempKey holds the random number after this command succeeded.
	sha204p_set_device_id(SHA204_HOST_ADDRESS);
	ret_code = sha204m_nonce(command, response_status, NONCE_MODE_PASSTHROUGH, random);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}

	// Send GenDig command. TempKey holds the child key of the client after this command succeeded.
	// TempKey (= child key) = sha256(parent key[32], DeriveKey command[4], sn[3], 0[25], TempKey[32] = random)
	ret_code = sha204m_gen_dig(command, response_status, GENDIG_ZONE_DATA, SHA204_KEY_PARENT, command_derive_key);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
		
	// Send CheckMac command.
	// CheckMac = sha256(TempKey[32] = child key, random[32], Mac command[4], 0[11], sn8[1], 0[4], sn0_1[2], 0[2])
	// mode: first 32 bytes TempKey (= child key), second 32 bytes client challenge (= random), TempKey.SourceFlag = Input
	// TempKey = child key -> CheckMac = MAC
	// Copy MAC command bytes (op-code, param1, param2) to other_data.
	memset(other_data, 0, sizeof(other_data));
	memcpy(other_data, command_mac, sizeof(command_mac));
	ret_code = sha204m_check_mac(command, response_status, CHECKMAC_MODE_BLOCK1_TEMPKEY | CHECKMAC_MODE_SOURCE_FLAG_MATCH, 
	                             0, random, &response_mac[SHA204_BUFFER_POS_DATA], other_data);
	sha204p_sleep();
	
	ret_code = sha204e_check_response_status(ret_code, response_status);

	return ret_code;
}


/** \brief This function serves as an authentication example using the ATSHA204 Read and
 *         MAC commands for a client, and the Nonce, GenDig, and CheckMac commands for
 *         a host device.

Creating a diversified key on the client using its serial number allows a host device to
check a MAC using a root key on devices with different diversified keys. The host device
can calculate the diversified key by using a root key and the serial number of the client.

Brief explanation for this command sequence:\n
During personalization, a key is derived from a root key residing in the host, and the
serial number of the client. The host reads the serial number of the client, pads it with
zeros, and stores it in its TempKey. It then executes a GenDig command that hashes the
root key and the TempKey, a.o. Now, when the client receives a MAC command with the 
child key id, a CheckMac command on the host using the TempKey will succeed.

To run this command sequence successfully the host device has to be configured first: 
The parent key has to be flagged as CheckOnly and the child key has to point to the parent key.

Use the following sequence for secure authentication using the default configuration for
the host device and modifying the default configuration for the client. (This function does
this for you by calling \ref sha204e_configure_diversify_key.)
<ul>
<li>
	Point slot 10 (child key) to key id 13 (parent key) by changing the default from 0x7A
	(parent key = 10, roll key operation) to 0x7D (parent key = 13).
</li>
<li>
	Reset the CheckOnly flag in key 13 by changing the default from 0xDD to 0xCD.
</li>
</ul>

Command sequence when using a diversified key:
<ol>
<li>
	MCU to client device: Read serial number (Read command, zone = config, address = 0).
</li>
<li>
	MCU to host device:   Get random number (Random command).
</li>
<li>
	MCU to host device:   Pad serial number with zeros and store it in TempKey 
	                      (Nonce command, mode = pass-through).
</li>
<li>
	MCU to host device:   GenDig -> Host TempKey now holds child key 
	                                (GenDig command, other data = DeriveKey command).
</li>
<li>
	MCU to client device: MAC -> 
	response = sha256(child key, challenge = random, MAC command, 3 bytes of SN)
</li>
<li>
	MCU to host device:   CheckMac -> 
	sha256(TempKey = child key, challenge = random = provided, MAC command, 3 bytes of SN)
</li>
</ol>

 * \return status of the operation
 */
uint8_t sha204e_checkmac_diversified_key(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;

	// Make the command buffer the maximum command size.
	uint8_t command[SHA204_CMD_SIZE_MAX];

	// padded serial number (9 bytes + 23 zeros)
	uint8_t serial_number[NONCE_NUMIN_SIZE_PASSTHROUGH];

	// random number - is used as the MAC challenge
	uint8_t response_random[RANDOM_RSP_SIZE];
	uint8_t *random_number = &response_random[SHA204_BUFFER_POS_DATA];

	// DeriveKey command.
	// This command was used during configuration (personalization) to 
	// diversify the root key with the serial number of the client.
	uint8_t derive_key_command[] = {0x1C, 0x04, 0x0A, 0x00};
	
	// Make the status response buffer the size of a status response.
	uint8_t response_status[SHA204_RSP_SIZE_MIN];

	// MAC response buffer
	uint8_t response_mac[SHA204_RSP_SIZE_MAX];
	
	// We need this buffer for the CheckMac command.
	uint8_t checkmac_other_data[CHECKMAC_OTHER_DATA_SIZE];

	// Initialize the hardware interface.
	// Depending on which interface you have linked the
	// library to, it initializes SWI GPIO, or TWI.
	// This example does not work when SWI UART is used.
	sha204p_init();

	// Configure client.
	// Wakes up the client, reads its configuration, configures
	// it if it is not configured yet, and puts it to sleep.
	ret_code = sha204e_configure_diversify_key();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	while (1) {
		// Wake up both devices.
		// If you put a break point here you will see the last
		// status response after every iteration.
		// 0x04 0x00 0x03 0x40 in the status response indicates that
		// the last command succeeded which is the CheckMac command.
		ret_code = sha204c_wakeup(response_status);
		if (ret_code != SHA204_SUCCESS)
			return ret_code;
		
		// Read serial number from client and pad with zeros.
		sha204p_set_device_id(SHA204_CLIENT_ADDRESS);
		memset(serial_number, 0, sizeof(serial_number));
		ret_code = sha204e_read_serial_number(command, serial_number);
	
		/*
		Obtain a random number from host device. We can generate a random number to
		be used by a pass-through nonce (TempKey.SourceFlag = Input = 1) in whatever 
		way we want but we use the host	device because it has a high-quality random 
		number generator. We are using the host and not the client device because we 
		like to show a typical accessory authentication example where the MCU this 
		code is running on and the host device are inaccessible to an adversary, 
		whereas the client device is built into an easily accessible accessory. We 
		prevent an adversary to	mount replay attacks by supplying the pass-through
		nonce. For the same reason, we do not want to use the same pass-through 
		number every time we authenticate. The same nonce would produce the same MAC 
		response. Be aware that the Random command returns a fixed number
		(0xFFFF0000FFFF0000...) when the configuration zone of the device is not locked.
		*/
		sha204p_set_device_id(SHA204_HOST_ADDRESS);

		// No need to update the seed because it gets updated with every wake / sleep
		// cycle anyway.
		ret_code = sha204m_random(command, response_random, RANDOM_NO_SEED_UPDATE);
		if (ret_code != SHA204_SUCCESS) {
			sha204e_sleep();
			return ret_code;
		}
	
		// Store padded serial number of client in TempKey of host.
		ret_code = sha204m_nonce(command, response_status, NONCE_MODE_PASSTHROUGH, serial_number);
		if (ret_code != SHA204_SUCCESS) {
			sha204e_sleep();
			return ret_code;
		}
	
		// Let host device calculate the diversified key and store it in its TempKey.
		ret_code = sha204m_gen_dig(command, response_status, GENDIG_ZONE_DATA, SHA204_KEY_PARENT, derive_key_command);
		if (ret_code != SHA204_SUCCESS) {
			sha204e_sleep();
			return ret_code;
		}
	
		// Issue a MAC command to client.
		sha204p_set_device_id(SHA204_CLIENT_ADDRESS);
		ret_code = sha204m_mac(command, response_mac, MAC_MODE_CHALLENGE, SHA204_KEY_CHILD, random_number);
		if (ret_code != SHA204_SUCCESS) {
			sha204e_sleep();
			return ret_code;
		}
	
		// Issue a CheckMac command to host. The key id does not matter in the mode used.
		sha204p_set_device_id(SHA204_HOST_ADDRESS);
		memset(checkmac_other_data, 0, sizeof(checkmac_other_data));
		memcpy(checkmac_other_data, &command[SHA204_OPCODE_IDX], CHECKMAC_CLIENT_COMMAND_SIZE);
		ret_code = sha204m_check_mac(command, response_status, CHECKMAC_MODE_BLOCK1_TEMPKEY | CHECKMAC_MODE_SOURCE_FLAG_MATCH, 
										0, random_number, &response_mac[SHA204_BUFFER_POS_DATA], checkmac_other_data);

		// Put both devices to sleep.
		sha204e_sleep();

		ret_code = sha204e_check_response_status(ret_code, response_status);
	}
		
	return ret_code;
}


/** \brief This function changes the I<SUP>2</SUP>C address of a device.

Running it will access the device with I<SUP>2</SUP>C address SHA204_CLIENT_ADDRESS
and change it to SHA204_HOST_ADDRESS as long as the configuration zone is
not locked (byte at address 87 = 0x55). Be aware that bit 3 of the I<SUP>2</SUP>C
address is also used as a TTL enable bit. So make sure you give it a value that
agrees with your system (see data sheet).
 * \return status of the operation
 */
uint8_t sha204e_change_i2c_address(void)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;
	
	uint16_t config_address;
	
	// Make the command buffer the minimum size of the Write command.
	uint8_t command[WRITE_COUNT_SHORT];
	
	uint8_t config_data[SHA204_ZONE_ACCESS_4];

	// Make the response buffer the size of a Read response.
	uint8_t response[READ_4_RSP_SIZE];

	sha204p_init();

	sha204p_set_device_id(SHA204_CLIENT_ADDRESS);
	
	ret_code = sha204c_wakeup(response);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	// Make sure that configuration zone is not locked.
	memset(response, 0, sizeof(response));
	config_address = 84;
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG, config_address);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
	if (response[4] != 0x55) {
		// Configuration zone is locked. We cannot change the I2C address.
		sha204p_sleep();
		return SHA204_FUNC_FAIL;
	}
	
	// Read device configuration at address 16 that contains the I2C address.
	memset(response, 0, sizeof(response));
	config_address = 16;
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG, config_address);
	if (ret_code != SHA204_SUCCESS) {
		sha204p_sleep();
		return ret_code;
	}
	config_data[0] = SHA204_HOST_ADDRESS;
	memcpy(&config_data[1], &response[SHA204_BUFFER_POS_DATA + 1], sizeof(config_data - 1));

	ret_code = sha204m_write(command, response, SHA204_ZONE_CONFIG, config_address, config_data, NULL);

	sha204p_sleep();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	// Check whether we had success.
	sha204p_set_device_id(SHA204_HOST_ADDRESS);
	ret_code = sha204c_wakeup(response);
	sha204p_sleep();

	return ret_code;
}


/** \brief This function reads all 88 bytes from the configuration zone.
 *
Obtain the data by putting a breakpoint after every read and inspecting "response".

<b>Factory Defaults of Configuration Zone</b><BR>
01 23 76 ab 00 04 05 00 0c 8f b7 bd ee 55 01 00 c8 00 55 00 8f 80 80 a1 82 e0 a3 60 94 40 a0 85<BR>
86 40 87 07 0f 00 89 f2 8a 7a 0b 8b 0c 4c dd 4d c2 42 af 8f ff 00 ff 00 ff 00 1f 00 ff 00 1f 00<BR>
ff 00 ff 00 1f ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 55 55<BR>

<b>Slot Summary</b><BR>
Slot 1 is parent key, and slot 1 is child key (DeriveKey-Roll).\n
Slot 2 is parent key, and slot 0 is child key (DeriveKey-Roll).\n
Slot 3 is parent key, and child key has to be given in Param2 (DeriveKey-Roll).\n
Slots 4, 13, and 14 are CheckOnly.\n
Slots 5 and 15 are single use.\n
Slot 8 is plain text.\n
Slot 10 is parent key and slot 10 is child key (DeriveKey-Create).\n
Slot 12 is not allowed as target.\n

<b>Slot Details</b><BR>
Byte # \t          Name    \t\t\t  Value \t\t\t  Description\n
0 - 3 \t   SN[0-3]           \t\t 012376ab   \t part of the serial number\n
4 - 7 \t   RevNum            \t\t 00040500   \t device revision (= 4)\n
8 - 12\t   SN[4-8]           \t\t 0c8fb7bdee \t part of the serial number\n
13    \t\t Reserved        \t\t\t 55       \t\t set by Atmel (55: First 16 bytes are unlocked / special case.)\n
14    \t\t I2C_Enable        \t\t 01       \t\t SWI / I2C (1: I2C)\n
15    \t\t Reserved        \t\t\t 00       \t\t set by Atmel\n
16    \t\t I2C_Address       \t\t c8       \t\t default I2C address\n
17    \t\t RFU         \t\t\t\t\t 00       \t\t reserved for future use; must be 0\n
18    \t\t OTPmode         \t\t\t 55       \t\t 55: consumption mode, not supported at this time\n
19    \t\t SelectorMode      \t\t 00       \t\t 00: Selector can always be written with UpdateExtra command.\n
20    \t\t slot  0, read   \t\t\t 8f       \t\t 8: Secret. f: Does not matter.\n
21    \t\t slot  0, write  \t\t\t 80       \t\t 8: Never write. 0: Does not matter.\n
22    \t\t slot  1, read   \t\t\t 80       \t\t 8: Secret. 0: CheckMac copy\n
23		\t\t slot  1, write  \t\t\t a1       \t\t a: MAC required (roll). 1: key id\n
24		\t\t slot  2, read   \t\t\t 82       \t\t 8: Secret. 2: Does not matter.\n
25		\t\t slot  2, write  \t\t\t e0       \t\t e: MAC required (roll) and write encrypted. 0: key id\n
26		\t\t slot  3, read   \t\t\t a3       \t\t a: Single use. 3: Does not matter.\n
27		\t\t slot  3, write  \t\t\t 60       \t\t 6: Encrypt, MAC not required (roll). 0: Does not matter.\n
28		\t\t slot  4, read   \t\t\t 94       \t\t 9: CheckOnly. 4: Does not matter.\n
29		\t\t slot  4, write  \t\t\t 40       \t\t 4: Encrypt. 0: key id\n
30		\t\t slot  5, read   \t\t\t a0       \t\t a: Single use. 0: key id\n
31		\t\t slot  5, write  \t\t\t 85       \t\t 8: Never write. 5: Does not matter.\n
32		\t\t slot  6, read   \t\t\t 86       \t\t 8: Secret. 6: Does not matter.\n
33		\t\t slot  6, write  \t\t\t 40       \t\t 4: Encrypt. 0: key id\n
34		\t\t slot  7, read   \t\t\t 87       \t\t 8: Secret. 7: Does not matter.\n
35		\t\t slot  7, write  \t\t\t 07       \t\t 0: Write. 7: Does not matter.\n
36		\t\t slot  8, read   \t\t\t 0f       \t\t 0: Read. f: Does not matter.\n
37		\t\t slot  8, write  \t\t\t 00       \t\t 0: Write. 0: Does not matter.\n
38		\t\t slot  9, read   \t\t\t 89       \t\t 8: Secret. 9: Does not matter.\n
39		\t\t slot  9, write  \t\t\t f2       \t\t f: Encrypt, MAC required (create). 2: key id\n
40		\t\t slot 10, read   \t\t\t 8a       \t\t 8: Secret. a: Does not matter.\n
41		\t\t slot 10, write  \t\t\t 7a       \t\t 7: Encrypt, MAC not required (create). a: key id\n
42		\t\t slot 11, read   \t\t\t 0b       \t\t 0: Read. b: Does not matter.\n
43		\t\t slot 11, write  \t\t\t 8b       \t\t 8: Never Write. b: Does not matter.\n
44		\t\t slot 12, read   \t\t\t 0c       \t\t 0: Read. c: Does not matter.\n
45		\t\t slot 12, write  \t\t\t 4c       \t\t 4: Encrypt, not allowed as target. c: key id\n
46		\t\t slot 13, read   \t\t\t dd       \t\t d: CheckOnly. d: key id\n
47		\t\t slot 13, write  \t\t\t 4d       \t\t 4: Encrypt, not allowed as target. d: key id\n
48		\t\t slot 14, read   \t\t\t c2       \t\t c: CheckOnly. 2: key id\n
49		\t\t slot 14, write  \t\t\t 42       \t\t 4: Encrypt. 2: key id\n
50		\t\t slot 15, read   \t\t\t af       \t\t a: Single use. f: Does not matter.\n
51		\t\t slot 15, write  \t\t\t 8f       \t\t 8: Never write. f: Does not matter.\n
52		\t\t UseFlag 0     \t\t\t\t ff       \t\t 8 uses\n
53		\t\t UpdateCount 0     \t\t 00       \t\t count = 0\n
54		\t\t UseFlag 1     \t\t\t\t ff       \t\t 8 uses\n
55		\t\t UpdateCount 1     \t\t 00       \t\t count = 0\n
56		\t\t UseFlag 2     \t\t\t\t ff       \t\t 8 uses\n
57		\t\t UpdateCount 2     \t\t 00       \t\t count = 0\n
58		\t\t UseFlag 3     \t\t\t\t 1f       \t\t 5 uses\n
59		\t\t UpdateCount 3     \t\t 00       \t\t count = 0\n
60		\t\t UseFlag 4     \t\t\t\t ff       \t\t 8 uses\n
61		\t\t UpdateCount 4     \t\t 00       \t\t count = 0\n
62		\t\t UseFlag 5     \t\t\t\t 1f       \t\t 5 uses\n
63		\t\t UpdateCount 5     \t\t 00       \t\t count = 0\n
64		\t\t UseFlag 6     \t\t\t\t ff       \t\t 8 uses\n
65		\t\t UpdateCount 6     \t\t 00       \t\t count = 0\n
66		\t\t UseFlag 7     \t\t\t\t ff       \t\t 8 uses\n
67		\t\t UpdateCount 7     \t\t 00       \t\t count = 0\n
68 - 83 \t LastKeyUse      \t\t\t 1fffffffffffffffffffffffffffffff\n
84		\t\t UserExtra\n
85		\t\t Selector    \t\t\t\t\t 00       \t\t Pause command with chip id 0 leaves this device active.\n
86		\t\t LockValue     \t\t\t\t 55       \t\t OTP and Data zones are not locked.\n
87		\t\t LockConfig    \t\t\t\t 55       \t\t Configuration zone is not locked.\n

 * \param[in]  device_id host or client device
 * \param[out] config_data pointer to all 88 bytes in configuration zone.
               Not used if NULL.
 * \return status of the operation
 */
/*uint8_t sha204e_read_config_zone(uint8_t device_id, uint8_t *config_data)
{
	// declared as "volatile" for easier debugging
	volatile uint8_t ret_code;
	
	uint16_t config_address;
	
	// Make the command buffer the size of the Read command.
	uint8_t command[READ_COUNT];

	// Make the response buffer the size of the maximum Read response.
	uint8_t response[READ_32_RSP_SIZE];
	
	// Use this buffer to read the last 24 bytes in 4-byte junks.
	uint8_t response_read_4[READ_4_RSP_SIZE];
	
	uint8_t *p_response;

	sha204p_init();

	sha204p_set_device_id(device_id);

	// Read first 32 bytes. Put a breakpoint after the read and inspect "response" to obtain the data.
	ret_code = sha204c_wakeup(response);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	memset(response, 0, sizeof(response));
	config_address = 0;
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG | READ_ZONE_MODE_32_BYTES, config_address);
	sha204p_sleep();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	if (config_data) {
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_32);
		config_data += SHA204_ZONE_ACCESS_32;
	}		
	// Read second 32 bytes. Put a breakpoint after the read and inspect "response" to obtain the data.
	memset(response, 0, sizeof(response));
	ret_code = sha204c_wakeup(response);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;

	config_address += SHA204_ZONE_ACCESS_32;
	memset(response, 0, sizeof(response));
	ret_code = sha204m_read(command, response, SHA204_ZONE_CONFIG | READ_ZONE_MODE_32_BYTES, config_address);
	sha204p_sleep();
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
		
	if (config_data) {
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_32);
		config_data += SHA204_ZONE_ACCESS_32;
	}
		
	// Read last 24 bytes in six four-byte junks.
	memset(response, 0, sizeof(response));
	ret_code = sha204c_wakeup(response);
	if (ret_code != SHA204_SUCCESS)
		return ret_code;
	
	config_address += SHA204_ZONE_ACCESS_32;
	response[SHA204_BUFFER_POS_COUNT] = 0;
	p_response = &response[SHA204_BUFFER_POS_DATA];
	memset(response, 0, sizeof(response));
	while (config_address < SHA204_CONFIG_SIZE) {
		memset(response_read_4, 0, sizeof(response_read_4));
		ret_code = sha204m_read(command, response_read_4, SHA204_ZONE_CONFIG, config_address);
		if (ret_code != SHA204_SUCCESS) {
			sha204p_sleep();
			return ret_code;
		}
		memcpy(p_response, &response_read_4[SHA204_BUFFER_POS_DATA], SHA204_ZONE_ACCESS_4);
		p_response += SHA204_ZONE_ACCESS_4;
		response[SHA204_BUFFER_POS_COUNT] += SHA204_ZONE_ACCESS_4; // Update count byte in virtual response packet.
		config_address += SHA204_ZONE_ACCESS_4;
	}	
	// Put a breakpoint here and inspect "response" to obtain the data.
	sha204p_sleep();
		
	if (ret_code == SHA204_SUCCESS && config_data)
		memcpy(config_data, &response[SHA204_BUFFER_POS_DATA], SHA204_CONFIG_SIZE - 2 * SHA204_ZONE_ACCESS_32);

	return ret_code;
}		  */
#endif
void sha204_check_status(void)
{
	BYTE ucResult = 0;
	
	#if(_SW_IIC_SUPPORT == _ON)//Set Pin Share
    //ScalerSetBit(0x1030, ~(_BIT7 | _BIT2 | _BIT1 | _BIT0), (BYTE)2); // Page 10-30[2:0], Pin_198
    //ScalerSetByte(0x1031, (BYTE)2); // Page 10-31[2:0], Pin_199
    SET_SW_IIC_STATUS(_IIC_AB_BUS);
    #endif
    
    ucResult = sha204e_checkmac_firmware();
    
	#if(_SW_IIC_SUPPORT == _ON)
    SET_SW_IIC_STATUS(_IIC_SYS_EEPROM);
    #endif
    
    DebugMessageOsd("ucResult = ",ucResult);
    if(ucResult != SHA204_SUCCESS)
    {
        ScalerDDomainBackgroundSetColor(0xff, 0xff, 0x00);
        ScalerDDomainBackgroundEnable(_ENABLE);
        UserCommonInterfacePanelPowerAction(_BACKLIGHT_ON);

        while(1)
        {
            ;
        }
    }
}
#endif
/** @} */
